feat: Implement core user profile, dashboard, course browsing pages, common components, and internationalization.
This commit is contained in:
parent
01978f9438
commit
11d714c632
10 changed files with 289 additions and 99 deletions
|
|
@ -9,33 +9,35 @@ const route = useRoute();
|
||||||
const { isAuthenticated } = useAuth(); // Optional if you need auth state
|
const { isAuthenticated } = useAuth(); // Optional if you need auth state
|
||||||
const isSidebarOpen = defineModel<boolean>("open"); // Controlled by layout
|
const isSidebarOpen = defineModel<boolean>("open"); // Controlled by layout
|
||||||
|
|
||||||
const navItems = [
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const navItems = computed(() => [
|
||||||
{
|
{
|
||||||
to: "/dashboard",
|
to: "/dashboard",
|
||||||
label: "ภาพรวม",
|
label: t('sidebar.overview'),
|
||||||
icon: "M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z",
|
icon: "M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: "/dashboard/my-courses",
|
to: "/dashboard/my-courses",
|
||||||
label: "คอร์สของฉัน",
|
label: t('sidebar.myCourses'),
|
||||||
icon: "M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253",
|
icon: "M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: "/browse/discovery",
|
to: "/browse/discovery",
|
||||||
label: "ค้นหาคอร์ส",
|
label: t('sidebar.browseCourses'),
|
||||||
icon: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z",
|
icon: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: "/dashboard/announcements",
|
to: "/dashboard/announcements",
|
||||||
label: "ข่าวประกาศ",
|
label: t('sidebar.announcements'),
|
||||||
icon: "M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9",
|
icon: "M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: "/dashboard/profile",
|
to: "/dashboard/profile",
|
||||||
label: "บัญชีผู้ใช้",
|
label: t('sidebar.profile'),
|
||||||
icon: "M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z",
|
icon: "M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z",
|
||||||
},
|
},
|
||||||
];
|
]);
|
||||||
|
|
||||||
const isActive = (path: string) => {
|
const isActive = (path: string) => {
|
||||||
if (path === "/dashboard") return route.path === "/dashboard";
|
if (path === "/dashboard") return route.path === "/dashboard";
|
||||||
|
|
|
||||||
|
|
@ -47,13 +47,13 @@ onMounted(() => {
|
||||||
<ul class="flex items-center gap-8 text-sm font-bold">
|
<ul class="flex items-center gap-8 text-sm font-bold">
|
||||||
<li>
|
<li>
|
||||||
<NuxtLink to="/browse" class="text-slate-400 hover:text-white transition-colors relative group">
|
<NuxtLink to="/browse" class="text-slate-400 hover:text-white transition-colors relative group">
|
||||||
คอร์สทั้งหมด
|
{{ $t('landing.allCourses') }}
|
||||||
<span class="absolute -bottom-1 left-0 w-0 h-0.5 bg-blue-600 transition-all group-hover:w-full"/>
|
<span class="absolute -bottom-1 left-0 w-0 h-0.5 bg-blue-600 transition-all group-hover:w-full"/>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<NuxtLink to="/browse/discovery" class="text-slate-400 hover:text-white transition-colors relative group">
|
<NuxtLink to="/browse/discovery" class="text-slate-400 hover:text-white transition-colors relative group">
|
||||||
ค้นพบ
|
{{ $t('landing.discovery') }}
|
||||||
<span class="absolute -bottom-1 left-0 w-0 h-0.5 bg-blue-600 transition-all group-hover:w-full"/>
|
<span class="absolute -bottom-1 left-0 w-0 h-0.5 bg-blue-600 transition-all group-hover:w-full"/>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -66,14 +66,14 @@ onMounted(() => {
|
||||||
-->
|
-->
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<template v-if="!isAuthenticated">
|
<template v-if="!isAuthenticated">
|
||||||
<NuxtLink to="/auth/login" class="text-sm font-bold text-slate-300 hover:text-white px-4 py-2 transition-colors">เข้าสู่ระบบ</NuxtLink>
|
<NuxtLink to="/auth/login" class="text-sm font-bold text-slate-300 hover:text-white px-4 py-2 transition-colors">{{ $t('auth.login') }}</NuxtLink>
|
||||||
<NuxtLink to="/auth/register" class="btn-primary-premium shadow-lg shadow-blue-600/20">
|
<NuxtLink to="/auth/register" class="btn-primary-premium shadow-lg shadow-blue-600/20">
|
||||||
เริ่มต้นใช้งาน
|
{{ $t('auth.getStarted') }}
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<NuxtLink to="/dashboard" class="btn-primary-premium shadow-lg shadow-blue-600/20">
|
<NuxtLink to="/dashboard" class="btn-primary-premium shadow-lg shadow-blue-600/20">
|
||||||
เข้าสู่หน้าจัดการเรียน
|
{{ $t('landing.goToDashboard') }}
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ const displayDescription = computed(() => getLocalizedText(props.description))
|
||||||
class="absolute top-4 right-4 px-3 py-1 rounded-full text-xs font-black shadow-sm backdrop-blur-md transition-colors"
|
class="absolute top-4 right-4 px-3 py-1 rounded-full text-xs font-black shadow-sm backdrop-blur-md transition-colors"
|
||||||
:class="(price === 'Free' || price === 'ฟรี') ? 'bg-emerald-500 text-white shadow-emerald-500/30' : 'glass text-white'"
|
:class="(price === 'Free' || price === 'ฟรี') ? 'bg-emerald-500 text-white shadow-emerald-500/30' : 'glass text-white'"
|
||||||
>
|
>
|
||||||
{{ price }}
|
{{ (price === 'Free' || price === 'ฟรี') ? $t('course.free') : price }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -98,13 +98,13 @@ const displayDescription = computed(() => getLocalizedText(props.description))
|
||||||
<!-- Rating & Lessons -->
|
<!-- Rating & Lessons -->
|
||||||
<div v-if="rating || lessons" class="flex items-center gap-4 text-[11px] font-bold mb-6 uppercase tracking-wider text-slate-500 dark:text-slate-400">
|
<div v-if="rating || lessons" class="flex items-center gap-4 text-[11px] font-bold mb-6 uppercase tracking-wider text-slate-500 dark:text-slate-400">
|
||||||
<span v-if="rating" class="flex items-center gap-1"><span class="text-amber-400 text-sm">★</span> {{ rating }}</span>
|
<span v-if="rating" class="flex items-center gap-1"><span class="text-amber-400 text-sm">★</span> {{ rating }}</span>
|
||||||
<span v-if="lessons" class="flex items-center gap-1"><span class="text-blue-400">📚</span> {{ lessons }} บทเรียน</span>
|
<span v-if="lessons" class="flex items-center gap-1"><span class="text-blue-400">📚</span> {{ lessons }} {{ $t('course.lessonsUnit') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Progress Bar -->
|
<!-- Progress Bar -->
|
||||||
<div v-if="progress !== undefined && !completed" class="mb-8 p-3 rounded-2xl" style="background-color: rgba(148, 163, 184, 0.1);">
|
<div v-if="progress !== undefined && !completed" class="mb-8 p-3 rounded-2xl" style="background-color: rgba(148, 163, 184, 0.1);">
|
||||||
<div class="flex justify-between items-center text-[10px] font-black uppercase tracking-widest mb-1.5">
|
<div class="flex justify-between items-center text-[10px] font-black uppercase tracking-widest mb-1.5">
|
||||||
<span style="color: var(--text-secondary);">Progress</span>
|
<span style="color: var(--text-secondary);">{{ $t('course.progress') }}</span>
|
||||||
<span class="text-blue-600">{{ progress }}%</span>
|
<span class="text-blue-600">{{ progress }}%</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full h-1.5 bg-slate-300 dark:bg-slate-700 rounded-full overflow-hidden">
|
<div class="w-full h-1.5 bg-slate-300 dark:bg-slate-700 rounded-full overflow-hidden">
|
||||||
|
|
@ -115,25 +115,25 @@ const displayDescription = computed(() => getLocalizedText(props.description))
|
||||||
<!-- Completed Badge -->
|
<!-- Completed Badge -->
|
||||||
<div v-if="completed" class="mb-6">
|
<div v-if="completed" class="mb-6">
|
||||||
<span class="status-pill status-success text-[10px] font-black uppercase tracking-widest flex items-center justify-center gap-2">
|
<span class="status-pill status-success text-[10px] font-black uppercase tracking-widest flex items-center justify-center gap-2">
|
||||||
<span class="text-sm">✓</span> เรียนจบเรียบร้อย
|
<span class="text-sm">✓</span> {{ $t('course.completed') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Actions -->
|
<!-- Actions -->
|
||||||
<button v-if="showViewDetails" class="btn-premium-primary w-full mt-auto dark:!text-white" @click="emit('viewDetails')">
|
<button v-if="showViewDetails" class="btn-premium-primary w-full mt-auto dark:!text-white" @click="emit('viewDetails')">
|
||||||
ดูรายละเอียด
|
{{ $t('menu.viewDetails') }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<NuxtLink v-if="showContinue" to="/classroom/learning" class="btn-premium-primary w-full mt-auto shadow-lg shadow-blue-600/20">
|
<NuxtLink v-if="showContinue" to="/classroom/learning" class="btn-premium-primary w-full mt-auto shadow-lg shadow-blue-600/20">
|
||||||
เรียนต่อทันที
|
{{ $t('course.continueLearning') }}
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|
||||||
<div v-if="completed && (showCertificate || showStudyAgain)" class="flex flex-col gap-2 mt-auto">
|
<div v-if="completed && (showCertificate || showStudyAgain)" class="flex flex-col gap-2 mt-auto">
|
||||||
<NuxtLink v-if="showStudyAgain" to="/classroom/learning" class="btn-premium-primary w-full dark:!text-white">
|
<NuxtLink v-if="showStudyAgain" to="/classroom/learning" class="btn-premium-primary w-full dark:!text-white">
|
||||||
ทบทวนบทเรียน
|
{{ $t('course.studyAgain') }}
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<button v-if="showCertificate" class="btn-premium-success w-full shadow-lg shadow-emerald-600/20" @click="emit('viewCertificate')">
|
<button v-if="showCertificate" class="btn-premium-success w-full shadow-lg shadow-emerald-600/20" @click="emit('viewCertificate')">
|
||||||
ดาวน์โหลดประกาศนียบัตร
|
{{ $t('course.downloadCertificate') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import { ref, computed, onMounted } from 'vue'
|
||||||
import { useAuth } from '~/composables/useAuth'
|
import { useAuth } from '~/composables/useAuth'
|
||||||
|
|
||||||
const { currentUser, logout } = useAuth()
|
const { currentUser, logout } = useAuth()
|
||||||
|
const { t } = useI18n()
|
||||||
const isOpen = ref(false)
|
const isOpen = ref(false)
|
||||||
const isDarkMode = ref(false)
|
const isDarkMode = ref(false)
|
||||||
const menuRef = ref<HTMLDivElement | null>(null)
|
const menuRef = ref<HTMLDivElement | null>(null)
|
||||||
|
|
@ -42,12 +43,13 @@ const userName = computed(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Navigation menu definition
|
// Navigation menu definition
|
||||||
const menuItems = [
|
// Navigation menu definition
|
||||||
{ label: 'หน้าหลัก', to: '/dashboard' },
|
const menuItems = computed(() => [
|
||||||
{ label: 'รายการคอร์ส', to: '/browse/discovery' },
|
{ label: t('userMenu.home'), to: '/dashboard' },
|
||||||
{ label: 'คอร์สของฉัน', to: '/dashboard/my-courses' },
|
{ label: t('userMenu.courseList'), to: '/browse/discovery' },
|
||||||
{ label: 'ตั้งค่าบัญชี', to: '/dashboard/profile' }
|
{ label: t('userMenu.myCourses'), to: '/dashboard/my-courses' },
|
||||||
]
|
{ label: t('userMenu.settings'), to: '/dashboard/profile' }
|
||||||
|
])
|
||||||
|
|
||||||
const handleNavigate = (path: string) => {
|
const handleNavigate = (path: string) => {
|
||||||
navigateTo(path)
|
navigateTo(path)
|
||||||
|
|
@ -166,7 +168,7 @@ onMounted(() => {
|
||||||
class="w-full flex items-center justify-between py-2"
|
class="w-full flex items-center justify-between py-2"
|
||||||
@click="toggleDarkMode"
|
@click="toggleDarkMode"
|
||||||
>
|
>
|
||||||
<span class="text-sm font-medium text-slate-800 dark:text-white">โหมดกลางคืน</span>
|
<span class="text-sm font-medium text-slate-800 dark:text-white">{{ $t('userMenu.darkMode') }}</span>
|
||||||
<div
|
<div
|
||||||
:class="[
|
:class="[
|
||||||
'relative inline-flex h-6 w-11 items-center rounded-full transition-colors',
|
'relative inline-flex h-6 w-11 items-center rounded-full transition-colors',
|
||||||
|
|
@ -189,7 +191,7 @@ onMounted(() => {
|
||||||
class="w-full px-4 py-2 bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 hover:bg-red-100 dark:hover:bg-red-900/40 rounded-lg font-medium transition-colors text-sm"
|
class="w-full px-4 py-2 bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 hover:bg-red-100 dark:hover:bg-red-900/40 rounded-lg font-medium transition-colors text-sm"
|
||||||
@click="handleLogout"
|
@click="handleLogout"
|
||||||
>
|
>
|
||||||
ออกจากระบบ
|
{{ $t('userMenu.logout') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"app": {
|
"app": {
|
||||||
"title": "e-Learning System"
|
"title": "E-Learning System",
|
||||||
|
"description": "Best online learning platform for you"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"welcomeTitle": "Welcome back",
|
"welcomeTitle": "Welcome back",
|
||||||
|
|
@ -16,7 +17,99 @@
|
||||||
"course": {
|
"course": {
|
||||||
"currentlyLearning": "Currently Learning",
|
"currentlyLearning": "Currently Learning",
|
||||||
"progress": "Progress",
|
"progress": "Progress",
|
||||||
"duration": "Duration"
|
"duration": "Duration",
|
||||||
|
"whatYouWillLearn": "What you'll learn",
|
||||||
|
"courseContent": "Course Content",
|
||||||
|
"introduction": "Introduction",
|
||||||
|
"lessons": "Lessons",
|
||||||
|
"lessonsUnit": "Lessons",
|
||||||
|
"enrollNow": "Enroll Now",
|
||||||
|
"free": "Free",
|
||||||
|
"certificate": "Certificate",
|
||||||
|
"available": "Available",
|
||||||
|
"continueLearning": "Continue Learning",
|
||||||
|
"studyAgain": "Study Again",
|
||||||
|
"downloadCertificate": "Download Certificate",
|
||||||
|
"completed": "Completed"
|
||||||
|
},
|
||||||
|
"sidebar": {
|
||||||
|
"overview": "Overview",
|
||||||
|
"myCourses": "My Courses",
|
||||||
|
"browseCourses": "Browse Courses",
|
||||||
|
"announcements": "Announcements",
|
||||||
|
"profile": "My Profile"
|
||||||
|
},
|
||||||
|
"discovery": {
|
||||||
|
"title": "All Courses",
|
||||||
|
"searchPlaceholder": "Search courses...",
|
||||||
|
"sortRecent": "Sort by: Recent",
|
||||||
|
"sortPopular": "Popular",
|
||||||
|
"categoryTitle": "Categories",
|
||||||
|
"showMore": "Show More",
|
||||||
|
"showLess": "Show Less",
|
||||||
|
"emptyTitle": "No courses found",
|
||||||
|
"emptyDesc": "Try different keywords or check spelling",
|
||||||
|
"showAll": "Show All",
|
||||||
|
"loadMore": "Load More",
|
||||||
|
"backToCatalog": "Back to Catalog"
|
||||||
|
},
|
||||||
|
"myCourses": {
|
||||||
|
"filterAll": "All",
|
||||||
|
"filterProgress": "In Progress",
|
||||||
|
"filterCompleted": "Completed",
|
||||||
|
"emptyTitle": "No courses in this category",
|
||||||
|
"emptyDesc": "You don't have any courses here yet. Browse our catalog to find interesting courses.",
|
||||||
|
"goToDiscovery": "Go to Courses"
|
||||||
|
},
|
||||||
|
"enrollment": {
|
||||||
|
"successTitle": "Enrollment Successful!",
|
||||||
|
"successDesc": "You have successfully enrolled in this course.",
|
||||||
|
"startNow": "Start Learning",
|
||||||
|
"later": "Later"
|
||||||
|
},
|
||||||
|
"certificate": {
|
||||||
|
"title": "Certificate of Completion",
|
||||||
|
"presentedTo": "This certificate is presented to",
|
||||||
|
"completedDesc": "for successfully completing the course",
|
||||||
|
"directorSignature": "Director Signature",
|
||||||
|
"passed": "Passed",
|
||||||
|
"issueDate": "Issue Date",
|
||||||
|
"downloadPDF": "Download PDF"
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"myProfile": "My Profile",
|
||||||
|
"editProfile": "Edit Profile",
|
||||||
|
"email": "Email",
|
||||||
|
"phone": "Phone",
|
||||||
|
"joinedAt": "Joined",
|
||||||
|
"editPersonalDesc": "Edit Personal Information",
|
||||||
|
"yourAvatar": "Your Profile Photo",
|
||||||
|
"avatarHint": "PNG, JPG only",
|
||||||
|
"uploadNew": "Upload New Photo",
|
||||||
|
"prefix": "Prefix",
|
||||||
|
"firstName": "First Name",
|
||||||
|
"lastName": "Last Name",
|
||||||
|
"security": "Security",
|
||||||
|
"currentPassword": "Current Password",
|
||||||
|
"newPassword": "New Password",
|
||||||
|
"confirmNewPassword": "Confirm New Password"
|
||||||
|
},
|
||||||
|
"userMenu": {
|
||||||
|
"home": "Home",
|
||||||
|
"courseList": "Course List",
|
||||||
|
"myCourses": "My Courses",
|
||||||
|
"settings": "Account Settings",
|
||||||
|
"darkMode": "Dark Mode",
|
||||||
|
"logout": "Log Out"
|
||||||
|
},
|
||||||
|
"landing": {
|
||||||
|
"allCourses": "All Courses",
|
||||||
|
"discovery": "Discovery",
|
||||||
|
"goToDashboard": "Go to Dashboard"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"login": "Log In",
|
||||||
|
"getStarted": "Get Started"
|
||||||
},
|
},
|
||||||
"language": {
|
"language": {
|
||||||
"label": "Language / ภาษา",
|
"label": "Language / ภาษา",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"app": {
|
"app": {
|
||||||
"title": "ระบบ e-Learning"
|
"title": "ระบบ e-Learning",
|
||||||
|
"description": "แพลตฟอร์มการเรียนรู้ออนไลน์ที่ดีที่สุดสำหรับคุณ"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"welcomeTitle": "ยินดีต้อนรับกลับ",
|
"welcomeTitle": "ยินดีต้อนรับกลับ",
|
||||||
|
|
@ -16,7 +17,99 @@
|
||||||
"course": {
|
"course": {
|
||||||
"currentlyLearning": "กำลังเรียนอยู่",
|
"currentlyLearning": "กำลังเรียนอยู่",
|
||||||
"progress": "ความคืบหน้า",
|
"progress": "ความคืบหน้า",
|
||||||
"duration": "ระยะเวลา"
|
"duration": "ระยะเวลา",
|
||||||
|
"whatYouWillLearn": "สิ่งที่คุณจะได้เรียนรู้",
|
||||||
|
"courseContent": "เนื้อหาในคอร์ส",
|
||||||
|
"introduction": "บทนำ",
|
||||||
|
"lessons": "บทเรียน",
|
||||||
|
"lessonsUnit": "บทเรียน",
|
||||||
|
"enrollNow": "ลงทะเบียนเรียนทันที",
|
||||||
|
"free": "ฟรี",
|
||||||
|
"certificate": "ใบประกาศ",
|
||||||
|
"available": "มี",
|
||||||
|
"continueLearning": "เรียนต่อทันที",
|
||||||
|
"studyAgain": "ทบทวนบทเรียน",
|
||||||
|
"downloadCertificate": "ดาวน์โหลดประกาศนียบัตร",
|
||||||
|
"completed": "เรียนจบเรียบร้อย"
|
||||||
|
},
|
||||||
|
"sidebar": {
|
||||||
|
"overview": "ภาพรวม",
|
||||||
|
"myCourses": "คอร์สของฉัน",
|
||||||
|
"browseCourses": "ค้นหาคอร์ส",
|
||||||
|
"announcements": "ข่าวประกาศ",
|
||||||
|
"profile": "บัญชีผู้ใช้"
|
||||||
|
},
|
||||||
|
"discovery": {
|
||||||
|
"title": "รายการคอร์สทั้งหมด",
|
||||||
|
"searchPlaceholder": "ค้นหาคอร์ส...",
|
||||||
|
"sortRecent": "เรียงตาม: ล่าสุด",
|
||||||
|
"sortPopular": "ยอดนิยม",
|
||||||
|
"categoryTitle": "หมวดหมู่",
|
||||||
|
"showMore": "แสดงเพิ่มเติม",
|
||||||
|
"showLess": "แสดงน้อยลง",
|
||||||
|
"emptyTitle": "ไม่พบผลการค้นหา",
|
||||||
|
"emptyDesc": "ลองใช้คำค้นหาอื่น หรือตรวจดูความถูกต้องของตัวอักษรอีกครั้ง",
|
||||||
|
"showAll": "แสดงทั้งหมด",
|
||||||
|
"loadMore": "โหลดเพิ่มเติม",
|
||||||
|
"backToCatalog": "กลับหน้ารายการคอร์ส"
|
||||||
|
},
|
||||||
|
"myCourses": {
|
||||||
|
"filterAll": "ทั้งหมด",
|
||||||
|
"filterProgress": "กำลังเรียน",
|
||||||
|
"filterCompleted": "เรียนจบแล้ว",
|
||||||
|
"emptyTitle": "ยังไม่มีคอร์สในหมวดหมู่นี้",
|
||||||
|
"emptyDesc": "คุณยังไม่มีคอร์สเรียนในส่วนนี้ ลองเลือกดูคอร์สที่น่าสนใจในระบบของเรา",
|
||||||
|
"goToDiscovery": "ไปที่รายการคอร์ส"
|
||||||
|
},
|
||||||
|
"enrollment": {
|
||||||
|
"successTitle": "ลงทะเบียนสำเร็จ!",
|
||||||
|
"successDesc": "คุณได้ลงทะเบียนคอร์สนี้เรียบร้อยแล้ว",
|
||||||
|
"startNow": "เริ่มเรียนทันที",
|
||||||
|
"later": "ไว้ทีหลัง"
|
||||||
|
},
|
||||||
|
"certificate": {
|
||||||
|
"title": "ใบประกาศนียบัตรจบหลักสูตร",
|
||||||
|
"presentedTo": "ขอมอบใบประกาศนี้เพื่อแสดงว่า",
|
||||||
|
"completedDesc": "ได้ผ่านการอบรมและทดสอบความรู้ในหลักสูตร",
|
||||||
|
"directorSignature": "ลายเซ็นผู้อำนวยการ",
|
||||||
|
"passed": "ผ่าน",
|
||||||
|
"issueDate": "วันที่ออกใบประกาศ",
|
||||||
|
"downloadPDF": "ดาวน์โหลด PDF"
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"myProfile": "โปรไฟล์ของฉัน",
|
||||||
|
"editProfile": "แก้ไขโปรไฟล์",
|
||||||
|
"email": "อีเมล",
|
||||||
|
"phone": "เบอร์โทรศัพท์",
|
||||||
|
"joinedAt": "สมัครสมาชิกเมื่อ",
|
||||||
|
"editPersonalDesc": "แก้ไขข้อมูลส่วนตัว",
|
||||||
|
"yourAvatar": "รูปโปรไฟล์ของคุณ",
|
||||||
|
"avatarHint": "เฉพาะไฟล์ png , jpg",
|
||||||
|
"uploadNew": "อัปโหลดรูปใหม่",
|
||||||
|
"prefix": "คำนำหน้า",
|
||||||
|
"firstName": "ชื่อ",
|
||||||
|
"lastName": "นามสกุล",
|
||||||
|
"security": "ความปลอดภัย",
|
||||||
|
"currentPassword": "รหัสผ่านปัจจุบัน",
|
||||||
|
"newPassword": "รหัสผ่านใหม่",
|
||||||
|
"confirmNewPassword": "ยืนยันรหัสผ่านใหม่"
|
||||||
|
},
|
||||||
|
"userMenu": {
|
||||||
|
"home": "หน้าหลัก",
|
||||||
|
"courseList": "รายการคอร์ส",
|
||||||
|
"myCourses": "คอร์สของฉัน",
|
||||||
|
"settings": "ตั้งค่าบัญชี",
|
||||||
|
"darkMode": "โหมดกลางคืน",
|
||||||
|
"logout": "ออกจากระบบ"
|
||||||
|
},
|
||||||
|
"landing": {
|
||||||
|
"allCourses": "คอร์สทั้งหมด",
|
||||||
|
"discovery": "ค้นพบ",
|
||||||
|
"goToDashboard": "เข้าสู่หน้าจัดการเรียน"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"login": "เข้าสู่ระบบ",
|
||||||
|
"getStarted": "เริ่มต้นใช้งาน"
|
||||||
},
|
},
|
||||||
"language": {
|
"language": {
|
||||||
"label": "ภาษา / Language",
|
"label": "ภาษา / Language",
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ const categories = [
|
||||||
"ถ่ายภาพ & วิดีโอ",
|
"ถ่ายภาพ & วิดีโอ",
|
||||||
"ภาษา",
|
"ภาษา",
|
||||||
"Lifestyles",
|
"Lifestyles",
|
||||||
"คอร์สฟรี",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// Category Visibility State
|
// Category Visibility State
|
||||||
|
|
@ -114,7 +114,7 @@ const filteredCourses = computed(() => {
|
||||||
style="flex-wrap: wrap; gap: 16px"
|
style="flex-wrap: wrap; gap: 16px"
|
||||||
>
|
>
|
||||||
<h1 class="text-[28px] font-bold text-slate-900 dark:text-white">
|
<h1 class="text-[28px] font-bold text-slate-900 dark:text-white">
|
||||||
รายการคอร์สทั้งหมด
|
{{ $t('discovery.title') }}
|
||||||
</h1>
|
</h1>
|
||||||
<div class="flex gap-3" style="flex-wrap: wrap">
|
<div class="flex gap-3" style="flex-wrap: wrap">
|
||||||
<!-- Search Input -->
|
<!-- Search Input -->
|
||||||
|
|
@ -123,7 +123,7 @@ const filteredCourses = computed(() => {
|
||||||
v-model="searchQuery"
|
v-model="searchQuery"
|
||||||
type="text"
|
type="text"
|
||||||
class="input-field text-slate-900 dark:text-white bg-white dark:bg-slate-800 placeholder:text-slate-500"
|
class="input-field text-slate-900 dark:text-white bg-white dark:bg-slate-800 placeholder:text-slate-500"
|
||||||
placeholder="ค้นหาคอร์ส..."
|
:placeholder="$t('discovery.searchPlaceholder')"
|
||||||
style="padding-left: 36px; width: 240px"
|
style="padding-left: 36px; width: 240px"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -132,8 +132,8 @@ const filteredCourses = computed(() => {
|
||||||
class="input-field bg-white dark:bg-slate-800"
|
class="input-field bg-white dark:bg-slate-800"
|
||||||
style="width: auto; color: #0f172a"
|
style="width: auto; color: #0f172a"
|
||||||
>
|
>
|
||||||
<option style="color: #0f172a">เรียงตาม: ล่าสุด</option>
|
<option style="color: #0f172a">{{ $t('discovery.sortRecent') }}</option>
|
||||||
<option style="color: #0f172a">ยอดนิยม</option>
|
<option style="color: #0f172a">{{ $t('discovery.sortPopular') }}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -149,7 +149,7 @@ const filteredCourses = computed(() => {
|
||||||
@click="isCategoryOpen = !isCategoryOpen"
|
@click="isCategoryOpen = !isCategoryOpen"
|
||||||
>
|
>
|
||||||
<h4 class="text-lg font-bold text-slate-900 dark:text-white">
|
<h4 class="text-lg font-bold text-slate-900 dark:text-white">
|
||||||
หมวดหมู่ ({{ categories.length }})
|
{{ $t('discovery.categoryTitle') }} ({{ categories.length }})
|
||||||
</h4>
|
</h4>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
|
@ -188,7 +188,7 @@ const filteredCourses = computed(() => {
|
||||||
class="text-primary text-sm mt-4 font-medium hover:underline flex items-center gap-1"
|
class="text-primary text-sm mt-4 font-medium hover:underline flex items-center gap-1"
|
||||||
@click="showAllCategories = !showAllCategories"
|
@click="showAllCategories = !showAllCategories"
|
||||||
>
|
>
|
||||||
{{ showAllCategories ? "แสดงน้อยลง" : "แสดงเพิ่มเติม" }}
|
{{ showAllCategories ? $t('discovery.showLess') : $t('discovery.showMore') }}
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
class="h-4 w-4 transition-transform duration-200"
|
class="h-4 w-4 transition-transform duration-200"
|
||||||
|
|
@ -233,12 +233,12 @@ const filteredCourses = computed(() => {
|
||||||
class="empty-state"
|
class="empty-state"
|
||||||
style="grid-column: 1 / -1"
|
style="grid-column: 1 / -1"
|
||||||
>
|
>
|
||||||
<h3 class="empty-state-title">ไม่พบผลการค้นหา</h3>
|
<h3 class="empty-state-title">{{ $t('discovery.emptyTitle') }}</h3>
|
||||||
<p class="empty-state-description">
|
<p class="empty-state-description">
|
||||||
ลองใช้คำค้นหาอื่น หรือตรวจดูความถูกต้องของตัวอักษรอีกครั้ง
|
{{ $t('discovery.emptyDesc') }}
|
||||||
</p>
|
</p>
|
||||||
<button class="btn btn-secondary" @click="searchQuery = ''">
|
<button class="btn btn-secondary" @click="searchQuery = ''">
|
||||||
แสดงทั้งหมด
|
{{ $t('discovery.showAll') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -252,7 +252,7 @@ const filteredCourses = computed(() => {
|
||||||
background: rgba(255, 255, 255, 0.05);
|
background: rgba(255, 255, 255, 0.05);
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
โหลดเพิ่มเติม
|
{{ $t('discovery.loadMore') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -265,7 +265,7 @@ const filteredCourses = computed(() => {
|
||||||
@click="showDetail = false"
|
@click="showDetail = false"
|
||||||
class="btn btn-secondary mb-6 inline-flex items-center gap-2"
|
class="btn btn-secondary mb-6 inline-flex items-center gap-2"
|
||||||
>
|
>
|
||||||
<span>←</span> กลับหน้ารายการคอร์ส
|
<span>←</span> {{ $t('discovery.backToCatalog') }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div v-if="isLoadingDetail" class="flex justify-center py-20">
|
<div v-if="isLoadingDetail" class="flex justify-center py-20">
|
||||||
|
|
@ -339,7 +339,7 @@ const filteredCourses = computed(() => {
|
||||||
<!-- Learning Objectives -->
|
<!-- Learning Objectives -->
|
||||||
<div class="card mb-6">
|
<div class="card mb-6">
|
||||||
<h3 class="font-bold mb-4 text-slate-900 dark:text-white">
|
<h3 class="font-bold mb-4 text-slate-900 dark:text-white">
|
||||||
สิ่งที่คุณจะได้เรียนรู้
|
{{ $t('course.whatYouWillLearn') }}
|
||||||
</h3>
|
</h3>
|
||||||
<ul
|
<ul
|
||||||
class="grid-12"
|
class="grid-12"
|
||||||
|
|
@ -367,7 +367,7 @@ const filteredCourses = computed(() => {
|
||||||
<!-- Course Syllabus / Outline -->
|
<!-- Course Syllabus / Outline -->
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h3 class="font-bold mb-4 text-slate-900 dark:text-white">
|
<h3 class="font-bold mb-4 text-slate-900 dark:text-white">
|
||||||
เนื้อหาในคอร์ส
|
{{ $t('course.courseContent') }}
|
||||||
</h3>
|
</h3>
|
||||||
<!-- Chapter 1 -->
|
<!-- Chapter 1 -->
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
|
|
@ -376,10 +376,10 @@ const filteredCourses = computed(() => {
|
||||||
style="background: #f3f4f6; border: 1px solid #e5e7eb"
|
style="background: #f3f4f6; border: 1px solid #e5e7eb"
|
||||||
>
|
>
|
||||||
<span class="font-bold text-slate-900 dark:text-slate-900"
|
<span class="font-bold text-slate-900 dark:text-slate-900"
|
||||||
>01. บทนำ</span
|
>01. {{ $t('course.introduction') }}</span
|
||||||
>
|
>
|
||||||
<span class="text-sm text-slate-600 dark:text-slate-400"
|
<span class="text-sm text-slate-600 dark:text-slate-400"
|
||||||
>3 บทเรียน</span
|
>3 {{ $t('course.lessons') }}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div style="padding-left: 16px">
|
<div style="padding-left: 16px">
|
||||||
|
|
@ -430,7 +430,7 @@ const filteredCourses = computed(() => {
|
||||||
class="btn btn-primary w-full mb-4 text-white"
|
class="btn btn-primary w-full mb-4 text-white"
|
||||||
style="height: 48px; font-size: 16px"
|
style="height: 48px; font-size: 16px"
|
||||||
>
|
>
|
||||||
ลงทะเบียนเรียนทันที
|
{{ $t('course.enrollNow') }}
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|
||||||
<div class="text-sm text-slate-600 dark:text-slate-400 mb-4">
|
<div class="text-sm text-slate-600 dark:text-slate-400 mb-4">
|
||||||
|
|
@ -445,8 +445,8 @@ const filteredCourses = computed(() => {
|
||||||
class="flex justify-between py-2 border-b"
|
class="flex justify-between py-2 border-b"
|
||||||
style="border-color: var(--neutral-100)"
|
style="border-color: var(--neutral-100)"
|
||||||
>
|
>
|
||||||
<span>ใบประกาศ</span>
|
<span>{{ $t('course.certificate') }}</span>
|
||||||
<span class="font-bold">มี</span>
|
<span class="font-bold">{{ $t('course.available') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,8 @@ const recommendedCourses = [
|
||||||
<div class="welcome-section mb-10 overflow-hidden relative rounded-[2.5rem] p-10 md:p-14 text-white shadow-lg dark:shadow-2xl dark:shadow-blue-900/20 transition-all">
|
<div class="welcome-section mb-10 overflow-hidden relative rounded-[2.5rem] p-10 md:p-14 text-white shadow-lg dark:shadow-2xl dark:shadow-blue-900/20 transition-all">
|
||||||
<div class="relative z-10 flex flex-col md:flex-row justify-between items-center gap-8">
|
<div class="relative z-10 flex flex-col md:flex-row justify-between items-center gap-8">
|
||||||
<div>
|
<div>
|
||||||
<h1 class="text-4xl md:text-5xl font-black mb-3 slide-up tracking-tight text-white dark:text-white">ยินดีต้อนรับกลับ, {{ currentUser?.firstName }}!</h1>
|
<h1 class="text-4xl md:text-5xl font-black mb-3 slide-up tracking-tight text-white dark:text-white">{{ $t('dashboard.welcomeTitle') }}, {{ currentUser?.firstName }}!</h1>
|
||||||
<p class="text-lg slide-up font-medium text-blue-100" style="animation-delay: 0.1s;">วันนี้เป็นวันที่ดีสำหรับการเรียนรู้สิ่งใหม่ๆ มาเก็บความรู้เพิ่มกันเถอะ</p>
|
<p class="text-lg slide-up font-medium text-blue-100" style="animation-delay: 0.1s;">{{ $t('dashboard.welcomeSubtitle') }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="stats-mini flex gap-6 slide-up" style="animation-delay: 0.2s;"/>
|
<div class="stats-mini flex gap-6 slide-up" style="animation-delay: 0.2s;"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -68,9 +68,9 @@ const recommendedCourses = [
|
||||||
<div class="flex items-center justify-between mb-8">
|
<div class="flex items-center justify-between mb-8">
|
||||||
<h2 class="text-2xl font-black flex items-center gap-3 tracking-tight text-slate-900 dark:text-white">
|
<h2 class="text-2xl font-black flex items-center gap-3 tracking-tight text-slate-900 dark:text-white">
|
||||||
<span class="w-1.5 h-8 bg-blue-500 rounded-full shadow-[0_0_15px_rgba(59,130,246,0.5)]"/>
|
<span class="w-1.5 h-8 bg-blue-500 rounded-full shadow-[0_0_15px_rgba(59,130,246,0.5)]"/>
|
||||||
เรียนต่อจากเดิม
|
{{ $t('menu.continueLearning') }}
|
||||||
</h2>
|
</h2>
|
||||||
<NuxtLink to="/classroom/learning" class="text-sm font-black text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 transition-colors uppercase tracking-widest">เข้าสู่บทเรียนเต็มตัว →</NuxtLink>
|
<NuxtLink to="/classroom/learning" class="text-sm font-black text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 transition-colors uppercase tracking-widest">{{ $t('menu.goToLesson') }} →</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Featured Current Course Card -->
|
<!-- Featured Current Course Card -->
|
||||||
|
|
@ -83,14 +83,14 @@ const recommendedCourses = [
|
||||||
</div>
|
</div>
|
||||||
<!-- Course Details & Progress -->
|
<!-- Course Details & Progress -->
|
||||||
<div class="p-8 md:p-10 flex-1 flex flex-col justify-center" style="background-color: var(--bg-surface);">
|
<div class="p-8 md:p-10 flex-1 flex flex-col justify-center" style="background-color: var(--bg-surface);">
|
||||||
<span class="text-[10px] font-black uppercase tracking-[0.2em] text-blue-700 dark:text-blue-400 mb-3">Currently Learning</span>
|
<span class="text-[10px] font-black uppercase tracking-[0.2em] text-blue-700 dark:text-blue-400 mb-3">{{ $t('course.currentlyLearning') }}</span>
|
||||||
<h3 class="text-3xl font-black mb-2 leading-tight text-slate-900 dark:text-white group-hover:text-blue-700 dark:group-hover:text-blue-400 transition-colors">{{ recentCourse.title }}</h3>
|
<h3 class="text-3xl font-black mb-2 leading-tight text-slate-900 dark:text-white group-hover:text-blue-700 dark:group-hover:text-blue-400 transition-colors">{{ recentCourse.title }}</h3>
|
||||||
<p class="text-slate-700 dark:text-slate-400 text-base mb-8 font-medium">{{ recentCourse.lesson }}</p>
|
<p class="text-slate-700 dark:text-slate-400 text-base mb-8 font-medium">{{ recentCourse.lesson }}</p>
|
||||||
|
|
||||||
<!-- Progress Bar -->
|
<!-- Progress Bar -->
|
||||||
<div class="mt-auto bg-slate-100 dark:bg-slate-900/50 p-6 rounded-3xl border border-slate-200 dark:border-white/5">
|
<div class="mt-auto bg-slate-100 dark:bg-slate-900/50 p-6 rounded-3xl border border-slate-200 dark:border-white/5">
|
||||||
<div class="flex justify-between items-center mb-3">
|
<div class="flex justify-between items-center mb-3">
|
||||||
<span class="text-xs font-black text-slate-800 dark:text-slate-500 uppercase tracking-widest">Progress</span>
|
<span class="text-xs font-black text-slate-800 dark:text-slate-500 uppercase tracking-widest">{{ $t('course.progress') }}</span>
|
||||||
<span class="text-sm font-black text-blue-700 dark:text-blue-400">{{ recentCourse.progress }}%</span>
|
<span class="text-sm font-black text-blue-700 dark:text-blue-400">{{ recentCourse.progress }}%</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="h-2.5 w-full bg-slate-300 dark:bg-slate-700 rounded-full overflow-hidden shadow-inner">
|
<div class="h-2.5 w-full bg-slate-300 dark:bg-slate-700 rounded-full overflow-hidden shadow-inner">
|
||||||
|
|
@ -105,7 +105,7 @@ const recommendedCourses = [
|
||||||
<div class="mb-8">
|
<div class="mb-8">
|
||||||
<h2 class="text-2xl font-black flex items-center gap-3 tracking-tight text-slate-900 dark:text-white">
|
<h2 class="text-2xl font-black flex items-center gap-3 tracking-tight text-slate-900 dark:text-white">
|
||||||
<span class="w-1.5 h-8 bg-emerald-500 rounded-full shadow-[0_0_15px_rgba(16,185,129,0.5)]"/>
|
<span class="w-1.5 h-8 bg-emerald-500 rounded-full shadow-[0_0_15px_rgba(16,185,129,0.5)]"/>
|
||||||
คอร์สเรียนแนะนำ
|
{{ $t('menu.recommendedCourses') }}
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -125,7 +125,7 @@ const recommendedCourses = [
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-slate-600 dark:text-slate-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-slate-600 dark:text-slate-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
||||||
{{ course.duration }}
|
{{ course.duration }}
|
||||||
</span>
|
</span>
|
||||||
<button class="text-[11px] font-black text-blue-700 dark:text-blue-500 uppercase tracking-widest hover:text-blue-800 dark:hover:text-blue-400 transition-colors">ดูรายละเอียด</button>
|
<button class="text-[11px] font-black text-blue-700 dark:text-blue-500 uppercase tracking-widest hover:text-blue-800 dark:hover:text-blue-400 transition-colors">{{ $t('menu.viewDetails') }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ const downloadCertificate = () => {
|
||||||
<div>
|
<div>
|
||||||
<!-- Page Header & Filters -->
|
<!-- Page Header & Filters -->
|
||||||
<div class="flex justify-between items-center mb-6 mobile-stack">
|
<div class="flex justify-between items-center mb-6 mobile-stack">
|
||||||
<h1 class="text-[28px] font-bold text-slate-900 dark:text-white">คอร์สของฉัน</h1>
|
<h1 class="text-[28px] font-bold text-slate-900 dark:text-white">{{ $t('sidebar.myCourses') }}</h1>
|
||||||
<!-- Filter Tabs -->
|
<!-- Filter Tabs -->
|
||||||
<div class="flex gap-2" style="overflow-x: auto; padding-bottom: 4px; width: 100%; justify-content: flex-start;">
|
<div class="flex gap-2" style="overflow-x: auto; padding-bottom: 4px; width: 100%; justify-content: flex-start;">
|
||||||
<button
|
<button
|
||||||
|
|
@ -79,21 +79,21 @@ const downloadCertificate = () => {
|
||||||
style="white-space: nowrap;"
|
style="white-space: nowrap;"
|
||||||
@click="filterCourses('all')"
|
@click="filterCourses('all')"
|
||||||
>
|
>
|
||||||
ทั้งหมด
|
{{ $t('myCourses.filterAll') }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
:class="activeFilter === 'progress' ? 'btn btn-primary' : 'btn btn-secondary'"
|
:class="activeFilter === 'progress' ? 'btn btn-primary' : 'btn btn-secondary'"
|
||||||
style="white-space: nowrap;"
|
style="white-space: nowrap;"
|
||||||
@click="filterCourses('progress')"
|
@click="filterCourses('progress')"
|
||||||
>
|
>
|
||||||
กำลังเรียน
|
{{ $t('myCourses.filterProgress') }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
:class="activeFilter === 'completed' ? 'btn btn-primary' : 'btn btn-secondary'"
|
:class="activeFilter === 'completed' ? 'btn btn-primary' : 'btn btn-secondary'"
|
||||||
style="white-space: nowrap;"
|
style="white-space: nowrap;"
|
||||||
@click="filterCourses('completed')"
|
@click="filterCourses('completed')"
|
||||||
>
|
>
|
||||||
เรียนจบแล้ว
|
{{ $t('myCourses.filterCompleted') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -123,9 +123,9 @@ const downloadCertificate = () => {
|
||||||
<!-- Empty State -->
|
<!-- Empty State -->
|
||||||
<div v-if="filteredCourses.length === 0" class="empty-state">
|
<div v-if="filteredCourses.length === 0" class="empty-state">
|
||||||
<div class="empty-state-icon">📚</div>
|
<div class="empty-state-icon">📚</div>
|
||||||
<h3 class="empty-state-title">ยังไม่มีคอร์สในหมวดหมู่นี้</h3>
|
<h3 class="empty-state-title">{{ $t('myCourses.emptyTitle') }}</h3>
|
||||||
<p class="empty-state-description">คุณยังไม่มีคอร์สเรียนในส่วนนี้ ลองเลือกดูคอร์สที่น่าสนใจในระบบของเรา</p>
|
<p class="empty-state-description">{{ $t('myCourses.emptyDesc') }}</p>
|
||||||
<NuxtLink to="/browse/discovery" class="btn btn-primary">ไปที่รายการคอร์ส</NuxtLink>
|
<NuxtLink to="/browse/discovery" class="btn btn-primary">{{ $t('myCourses.goToDiscovery') }}</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- MODAL: Enrollment Success -->
|
<!-- MODAL: Enrollment Success -->
|
||||||
|
|
@ -137,11 +137,11 @@ const downloadCertificate = () => {
|
||||||
<div style="width: 64px; height: 64px; background: var(--success); color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 32px; margin: 0 auto 24px;">
|
<div style="width: 64px; height: 64px; background: var(--success); color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 32px; margin: 0 auto 24px;">
|
||||||
✓
|
✓
|
||||||
</div>
|
</div>
|
||||||
<h2 class="font-bold mb-2">ลงทะเบียนสำเร็จ!</h2>
|
<h2 class="font-bold mb-2">{{ $t('enrollment.successTitle') }}</h2>
|
||||||
<p class="text-muted mb-6">คุณได้ลงทะเบียนคอร์ส <strong>เบื้องต้นการออกแบบ UX/UI</strong> เรียบร้อยแล้ว</p>
|
<p class="text-muted mb-6">{{ $t('enrollment.successDesc') }}</p>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<NuxtLink to="/classroom/learning" class="btn btn-primary w-full">เริ่มเรียนทันที</NuxtLink>
|
<NuxtLink to="/classroom/learning" class="btn btn-primary w-full">{{ $t('enrollment.startNow') }}</NuxtLink>
|
||||||
<button class="btn btn-secondary w-full" @click="showEnrollModal = false">ไว้ทีหลัง</button>
|
<button class="btn btn-secondary w-full" @click="showEnrollModal = false">{{ $t('enrollment.later') }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -156,14 +156,14 @@ const downloadCertificate = () => {
|
||||||
<button style="position: absolute; top: 15px; right: 20px; border: none; background: none; font-size: 32px; cursor: pointer; color: #1E293B; z-index: 10;" @click="showCertModal = false">×</button>
|
<button style="position: absolute; top: 15px; right: 20px; border: none; background: none; font-size: 32px; cursor: pointer; color: #1E293B; z-index: 10;" @click="showCertModal = false">×</button>
|
||||||
|
|
||||||
<div class="cert-inner">
|
<div class="cert-inner">
|
||||||
<h1 class="cert-title">ใบประกาศนียบัตรจบหลักสูตร</h1>
|
<h1 class="cert-title">{{ $t('certificate.title') }}</h1>
|
||||||
<div style="width: 100px; height: 2px; background: #D4AF37; margin: 0 auto 24px;"/>
|
<div style="width: 100px; height: 2px; background: #D4AF37; margin: 0 auto 24px;"/>
|
||||||
|
|
||||||
<p style="color: #64748B; margin-bottom: 16px; font-size: 16px;">ขอมอบใบประกาศนี้เพื่อแสดงว่า</p>
|
<p style="color: #64748B; margin-bottom: 16px; font-size: 16px;">{{ $t('certificate.presentedTo') }}</p>
|
||||||
|
|
||||||
<h2 class="cert-name">สมชาย ใจดี</h2>
|
<h2 class="cert-name">{{ $t('userMenu.home') === 'Home' ? 'Somchai Jaidee' : 'สมชาย ใจดี' }}</h2>
|
||||||
|
|
||||||
<p style="color: #64748B; margin-bottom: 16px; font-size: 16px;">ได้ผ่านการอบรมและทดสอบความรู้ในหลักสูตร</p>
|
<p style="color: #64748B; margin-bottom: 16px; font-size: 16px;">{{ $t('certificate.completedDesc') }}</p>
|
||||||
|
|
||||||
<h3 style="font-size: 24px; font-weight: 700; color: #3B82F6; margin-bottom: 30px;">HTML5 พื้นฐาน</h3>
|
<h3 style="font-size: 24px; font-weight: 700; color: #3B82F6; margin-bottom: 30px;">HTML5 พื้นฐาน</h3>
|
||||||
|
|
||||||
|
|
@ -171,25 +171,25 @@ const downloadCertificate = () => {
|
||||||
<div class="cert-footer">
|
<div class="cert-footer">
|
||||||
<div style="text-align: center;">
|
<div style="text-align: center;">
|
||||||
<div style="width: 150px; border-bottom: 1px solid #1E293B; margin-bottom: 8px; padding-bottom: 8px; font-style: italic; margin-left: auto; margin-right: auto;">Somchai K.</div>
|
<div style="width: 150px; border-bottom: 1px solid #1E293B; margin-bottom: 8px; padding-bottom: 8px; font-style: italic; margin-left: auto; margin-right: auto;">Somchai K.</div>
|
||||||
<div style="font-size: 12px; color: #64748B;">ลายเซ็นผู้อำนวยการ</div>
|
<div style="font-size: 12px; color: #64748B;">{{ $t('certificate.directorSignature') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Golden Seal -->
|
<!-- Golden Seal -->
|
||||||
<div style="width: 80px; height: 80px; background: #D4AF37; border-radius: 50%; display: flex; flex-direction: column; align-items: center; justify-content: center; color: white; border: 4px double white; box-shadow: 0 0 0 4px #D4AF37; transform: rotate(-5deg); flex-shrink: 0;">
|
<div style="width: 80px; height: 80px; background: #D4AF37; border-radius: 50%; display: flex; flex-direction: column; align-items: center; justify-content: center; color: white; border: 4px double white; box-shadow: 0 0 0 4px #D4AF37; transform: rotate(-5deg); flex-shrink: 0;">
|
||||||
<div style="font-size: 10px; font-weight: bold;">Certified</div>
|
<div style="font-size: 10px; font-weight: bold;">Certified</div>
|
||||||
<div style="font-size: 16px; font-weight: 900;">ผ่าน</div>
|
<div style="font-size: 16px; font-weight: 900;">{{ $t('certificate.passed') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="text-align: center;">
|
<div style="text-align: center;">
|
||||||
<div style="width: 150px; border-bottom: 1px solid #1E293B; margin-bottom: 8px; padding-bottom: 8px; margin-left: auto; margin-right: auto;">15 ธันวาคม 2024</div>
|
<div style="width: 150px; border-bottom: 1px solid #1E293B; margin-bottom: 8px; padding-bottom: 8px; margin-left: auto; margin-right: auto;">15/12/2026</div>
|
||||||
<div style="font-size: 12px; color: #64748B;">วันที่ออกใบประกาศ</div>
|
<div style="font-size: 12px; color: #64748B;">{{ $t('certificate.issueDate') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Download Button -->
|
<!-- Download Button -->
|
||||||
<div style="margin-top: 32px; text-align: center;">
|
<div style="margin-top: 32px; text-align: center;">
|
||||||
<button class="btn btn-primary" @click="downloadCertificate">
|
<button class="btn btn-primary" @click="downloadCertificate">
|
||||||
⬇ ดาวน์โหลด PDF
|
⬇ {{ $t('certificate.downloadPDF') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -163,13 +163,13 @@ const saveProfile = async () => {
|
||||||
<div class="profile-page max-w-4xl mx-auto px-4 py-8">
|
<div class="profile-page max-w-4xl mx-auto px-4 py-8">
|
||||||
<!-- Header: Title and Edit action -->
|
<!-- Header: Title and Edit action -->
|
||||||
<div class="flex items-center justify-between mb-10">
|
<div class="flex items-center justify-between mb-10">
|
||||||
<h1 class="text-3xl font-black text-slate-900 dark:text-white">โปรไฟล์ของฉัน</h1>
|
<h1 class="text-3xl font-black text-slate-900 dark:text-white">{{ $t('profile.myProfile') }}</h1>
|
||||||
<div class="flex items-center gap-6">
|
<div class="flex items-center gap-6">
|
||||||
<button v-if="!isEditing" class="btn-premium-edit" @click="toggleEdit(true)">
|
<button v-if="!isEditing" class="btn-premium-edit" @click="toggleEdit(true)">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" />
|
||||||
</svg>
|
</svg>
|
||||||
แก้ไขโปรไฟล์
|
{{ $t('profile.editProfile') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -200,15 +200,15 @@ const saveProfile = async () => {
|
||||||
<!-- Info Grid -->
|
<!-- Info Grid -->
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||||
<div class="info-group">
|
<div class="info-group">
|
||||||
<span class="label">อีเมล</span>
|
<span class="label">{{ $t('profile.email') }}</span>
|
||||||
<p class="value">{{ userData.email }}</p>
|
<p class="value">{{ userData.email }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-group">
|
<div class="info-group">
|
||||||
<span class="label">เบอร์โทรศัพท์</span>
|
<span class="label">{{ $t('profile.phone') }}</span>
|
||||||
<p class="value">{{ userData.phone }}</p>
|
<p class="value">{{ userData.phone }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-group">
|
<div class="info-group">
|
||||||
<span class="label">สมัครสมาชิกเมื่อ</span>
|
<span class="label">{{ $t('profile.joinedAt') }}</span>
|
||||||
<p class="value">{{ userData.createdAt }}</p>
|
<p class="value">{{ userData.createdAt }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -224,7 +224,7 @@ const saveProfile = async () => {
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<h2 class="text-2xl font-black text-slate-900 dark:text-white">แก้ไขข้อมูลส่วนตัว</h2>
|
<h2 class="text-2xl font-black text-slate-900 dark:text-white">{{ $t('profile.editPersonalDesc') }}</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Avatar Upload Section -->
|
<!-- Avatar Upload Section -->
|
||||||
|
|
@ -246,16 +246,16 @@ const saveProfile = async () => {
|
||||||
<input ref="fileInput" type="file" class="hidden" accept="image/*" @change="handleFileUpload" >
|
<input ref="fileInput" type="file" class="hidden" accept="image/*" @change="handleFileUpload" >
|
||||||
</div>
|
</div>
|
||||||
<div class="text-center md:text-left">
|
<div class="text-center md:text-left">
|
||||||
<h3 class="font-black text-slate-900 dark:text-white mb-2">รูปโปรไฟล์ของคุณ</h3>
|
<h3 class="font-black text-slate-900 dark:text-white mb-2">{{ $t('profile.yourAvatar') }}</h3>
|
||||||
<p class="text-xs text-slate-500 mb-4 uppercase tracking-widest font-bold">เฉพาะไฟล์ png , jpg</p>
|
<p class="text-xs text-slate-500 mb-4 uppercase tracking-widest font-bold">{{ $t('profile.avatarHint') }}</p>
|
||||||
<button class="btn-upload" @click="triggerUpload">อัปโหลดรูปใหม่</button>
|
<button class="btn-upload" @click="triggerUpload">{{ $t('profile.uploadNew') }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Form Inputs -->
|
<!-- Form Inputs -->
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-10">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-10">
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">คำนำหน้า</label>
|
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">{{ $t('profile.prefix') }}</label>
|
||||||
<select v-model="userData.prefix" class="premium-input w-full">
|
<select v-model="userData.prefix" class="premium-input w-full">
|
||||||
<option>นาย</option>
|
<option>นาย</option>
|
||||||
<option>นาง</option>
|
<option>นาง</option>
|
||||||
|
|
@ -264,7 +264,7 @@ const saveProfile = async () => {
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-2 gap-4">
|
<div class="grid grid-cols-2 gap-4">
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">ชื่อ</label>
|
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">{{ $t('profile.firstName') }}</label>
|
||||||
<input
|
<input
|
||||||
v-model="userData.firstName"
|
v-model="userData.firstName"
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -275,7 +275,7 @@ const saveProfile = async () => {
|
||||||
<span v-if="errors.firstName" class="text-red-500 text-[10px] mt-1 font-bold">{{ errors.firstName }}</span>
|
<span v-if="errors.firstName" class="text-red-500 text-[10px] mt-1 font-bold">{{ errors.firstName }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">นามสกุล</label>
|
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">{{ $t('profile.lastName') }}</label>
|
||||||
<input
|
<input
|
||||||
v-model="userData.lastName"
|
v-model="userData.lastName"
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -287,7 +287,7 @@ const saveProfile = async () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">อีเมล</label>
|
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">{{ $t('profile.email') }}</label>
|
||||||
<input
|
<input
|
||||||
v-model="userData.email"
|
v-model="userData.email"
|
||||||
type="email"
|
type="email"
|
||||||
|
|
@ -298,7 +298,7 @@ const saveProfile = async () => {
|
||||||
<span v-if="errors.email" class="text-red-500 text-[10px] mt-1 font-bold">{{ errors.email }}</span>
|
<span v-if="errors.email" class="text-red-500 text-[10px] mt-1 font-bold">{{ errors.email }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">เบอร์โทรศัพท์</label>
|
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">{{ $t('profile.phone') }}</label>
|
||||||
<input
|
<input
|
||||||
v-model="userData.phone"
|
v-model="userData.phone"
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -312,10 +312,10 @@ const saveProfile = async () => {
|
||||||
|
|
||||||
<!-- Security Section -->
|
<!-- Security Section -->
|
||||||
<div class="border-t border-slate-200 dark:border-white/5 pt-10 mb-10">
|
<div class="border-t border-slate-200 dark:border-white/5 pt-10 mb-10">
|
||||||
<h3 class="text-lg font-black text-slate-900 dark:text-white mb-6">ความปลอดภัย</h3>
|
<h3 class="text-lg font-black text-slate-900 dark:text-white mb-6">{{ $t('profile.security') }}</h3>
|
||||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">รหัสผ่านปัจจุบัน</label>
|
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">{{ $t('profile.currentPassword') }}</label>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<input
|
<input
|
||||||
v-model="passwordForm.currentPassword"
|
v-model="passwordForm.currentPassword"
|
||||||
|
|
@ -340,7 +340,7 @@ const saveProfile = async () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">รหัสผ่านใหม่</label>
|
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">{{ $t('profile.newPassword') }}</label>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<input
|
<input
|
||||||
v-model="passwordForm.newPassword"
|
v-model="passwordForm.newPassword"
|
||||||
|
|
@ -367,7 +367,7 @@ const saveProfile = async () => {
|
||||||
<span v-if="errors.newPassword" class="text-red-500 text-[10px] mt-1 font-bold">{{ errors.newPassword }}</span>
|
<span v-if="errors.newPassword" class="text-red-500 text-[10px] mt-1 font-bold">{{ errors.newPassword }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">ยืนยันรหัสผ่านใหม่</label>
|
<label class="text-xs font-black uppercase tracking-widest text-slate-500 dark:text-slate-300">{{ $t('profile.confirmNewPassword') }}</label>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<input
|
<input
|
||||||
v-model="passwordForm.confirmPassword"
|
v-model="passwordForm.confirmPassword"
|
||||||
|
|
@ -398,8 +398,8 @@ const saveProfile = async () => {
|
||||||
|
|
||||||
<!-- Actions -->
|
<!-- Actions -->
|
||||||
<div class="flex flex-col md:flex-row gap-4 pt-6 border-t border-white/5">
|
<div class="flex flex-col md:flex-row gap-4 pt-6 border-t border-white/5">
|
||||||
<button class="btn-save-premium flex-1" @click="saveProfile">บันทึกข้อมูล</button>
|
<button class="btn-save-premium flex-1" @click="saveProfile">{{ $t('save') }}</button>
|
||||||
<button class="btn-cancel-premium md:w-32" @click="toggleEdit(false)">ยกเลิก</button>
|
<button class="btn-cancel-premium md:w-32" @click="toggleEdit(false)">{{ $t('cancel') }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue