login with api
This commit is contained in:
parent
d8a9909eb9
commit
ff5b189b2f
16 changed files with 1241 additions and 66 deletions
|
|
@ -1,7 +1,59 @@
|
|||
<template>
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold mb-6">Dashboard</h1>
|
||||
<p class="text-gray-600 mb-8">ยินดีต้อนรับ, {{ authStore.user?.fullName }}</p>
|
||||
<!-- Header -->
|
||||
<div class="mb-8">
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold text-gray-900">
|
||||
สวัสดี, {{ authStore.user?.fullName || 'ผู้ดูแลระบบ' }}
|
||||
</h1>
|
||||
<p class="text-gray-600 mt-2">ยินดีต้อนรับกลับสู่ระบบ</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="text-right">
|
||||
<div class="text-sm font-semibold text-gray-900">{{ authStore.user?.fullName || 'ผู้ดูแลระบบ' }}</div>
|
||||
<div class="text-xs text-gray-500">{{ authStore.user?.role || 'ADMIN' }}</div>
|
||||
</div>
|
||||
<div
|
||||
class="w-12 h-12 bg-primary-100 rounded-full flex items-center justify-center text-2xl cursor-pointer hover:bg-primary-200 transition"
|
||||
>
|
||||
👨💼
|
||||
<q-menu>
|
||||
<q-list style="min-width: 200px">
|
||||
<!-- User Info Header -->
|
||||
<q-item class="bg-primary-50">
|
||||
<q-item-section>
|
||||
<q-item-label class="text-weight-bold">{{ authStore.user?.fullName }}</q-item-label>
|
||||
<q-item-label caption>{{ authStore.user?.email }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator />
|
||||
|
||||
<!-- Profile -->
|
||||
<q-item clickable v-close-popup @click="goToProfile">
|
||||
<q-item-section avatar>
|
||||
<q-icon name="person" />
|
||||
</q-item-section>
|
||||
<q-item-section>โปรไฟล์</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator />
|
||||
|
||||
<!-- Logout -->
|
||||
<q-item clickable v-close-popup @click="handleLogout">
|
||||
<q-item-section avatar>
|
||||
<q-icon name="logout" color="negative" />
|
||||
</q-item-section>
|
||||
<q-item-section class="text-negative">ออกจากระบบ</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Stats Cards -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
|
||||
<div class="card">
|
||||
|
|
@ -28,7 +80,6 @@
|
|||
<p class="text-gray-600 text-sm">เรียนจบแล้ว</p>
|
||||
<p class="text-3xl font-bold text-accent-500">45</p>
|
||||
</div>
|
||||
<q-icon name="emoji_events" size="48px" class="text-accent-200" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -52,8 +103,20 @@
|
|||
</template>
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
layout: 'instructor',
|
||||
middleware: 'instructor'
|
||||
layout: 'admin',
|
||||
middleware: 'auth'
|
||||
});
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const router = useRouter();
|
||||
|
||||
// Navigation functions
|
||||
const goToProfile = () => {
|
||||
router.push('/admin/profile');
|
||||
};
|
||||
|
||||
const handleLogout = () => {
|
||||
authStore.logout();
|
||||
router.push('/login');
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,14 +1,55 @@
|
|||
<template>
|
||||
<div>
|
||||
<!-- Header -->
|
||||
<div class="flex justify-between items-center mb-8">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-gray-900">สวัสดี, อาจารย์ทดสอบ 👋</h1>
|
||||
<p class="text-gray-600 mt-2">ยินดีต้อนรับกลับสู่ระบบ</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="w-12 h-12 bg-primary-100 rounded-full flex items-center justify-center text-2xl">
|
||||
👤
|
||||
<div class="mb-8">
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold text-gray-900">
|
||||
สวัสดี, {{ authStore.user?.fullName || 'อาจารย์' }}
|
||||
</h1>
|
||||
<p class="text-gray-600 mt-2">ยินดีต้อนรับกลับสู่ระบบ</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="text-right">
|
||||
<div class="text-sm font-semibold text-gray-900">{{ authStore.user?.fullName || 'อาจารย์ทดสอบ' }}</div>
|
||||
<div class="text-xs text-gray-500">{{ authStore.user?.role || 'INSTRUCTOR' }}</div>
|
||||
</div>
|
||||
<div
|
||||
class="w-12 h-12 bg-primary-100 rounded-full flex items-center justify-center text-2xl cursor-pointer hover:bg-primary-200 transition"
|
||||
>
|
||||
👨🏫
|
||||
<q-menu>
|
||||
<q-list style="min-width: 200px">
|
||||
<!-- User Info Header -->
|
||||
<q-item class="bg-primary-50">
|
||||
<q-item-section>
|
||||
<q-item-label class="text-weight-bold">{{ authStore.user?.fullName }}</q-item-label>
|
||||
<q-item-label caption>{{ authStore.user?.email }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator />
|
||||
|
||||
<!-- Profile -->
|
||||
<q-item clickable v-close-popup @click="goToProfile">
|
||||
<q-item-section avatar>
|
||||
<q-icon name="person" />
|
||||
</q-item-section>
|
||||
<q-item-section>โปรไฟล์</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator />
|
||||
|
||||
<!-- Logout -->
|
||||
<q-item clickable v-close-popup @click="handleLogout">
|
||||
<q-item-section avatar>
|
||||
<q-icon name="logout" color="negative" />
|
||||
</q-item-section>
|
||||
<q-item-section class="text-negative">ออกจากระบบ</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -96,9 +137,24 @@ definePageMeta({
|
|||
middleware: 'auth'
|
||||
});
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const instructorStore = useInstructorStore();
|
||||
const router = useRouter();
|
||||
|
||||
// Navigation functions
|
||||
const goToProfile = () => {
|
||||
router.push('/instructor/profile');
|
||||
};
|
||||
|
||||
const goToSettings = () => {
|
||||
router.push('/instructor/settings');
|
||||
};
|
||||
|
||||
const handleLogout = () => {
|
||||
authStore.logout();
|
||||
router.push('/login');
|
||||
};
|
||||
|
||||
// Fetch dashboard data on mount
|
||||
onMounted(() => {
|
||||
instructorStore.fetchDashboardData();
|
||||
|
|
|
|||
419
frontend_management/pages/instructor/profile/index.vue
Normal file
419
frontend_management/pages/instructor/profile/index.vue
Normal file
|
|
@ -0,0 +1,419 @@
|
|||
<template>
|
||||
<div>
|
||||
<!-- Header -->
|
||||
<div class="mb-6">
|
||||
<h1 class="text-3xl font-bold text-gray-900">โปรไฟล์ของฉัน</h1>
|
||||
<p class="text-gray-600 mt-2">จัดการข้อมูลส่วนตัวของคุณ</p>
|
||||
</div>
|
||||
|
||||
<!-- Profile Card -->
|
||||
<AppCard class="mb-10 ">
|
||||
<div class="flex flex-col md:flex-row gap-8">
|
||||
<!-- Avatar Section -->
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="w-32 h-32 bg-primary-100 rounded-full flex items-center justify-center text-6xl mb-4">
|
||||
{{ profile.avatar }}
|
||||
</div>
|
||||
<q-btn
|
||||
outline
|
||||
color="primary"
|
||||
label="เปลี่ยนรูป"
|
||||
icon="photo_camera"
|
||||
@click="handleAvatarUpload"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Profile Info -->
|
||||
<div class="flex-1">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<div class="text-sm text-gray-600 mb-1">ชื่อ-นามสกุล</div>
|
||||
<div class="text-lg font-semibold text-gray-900">{{ profile.fullName }}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="text-sm text-gray-600 mb-1">อีเมล</div>
|
||||
<div class="text-lg text-gray-900">{{ profile.email }}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="text-sm text-gray-600 mb-1">Username</div>
|
||||
<div class="text-lg text-gray-900">{{ profile.username }}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="text-sm text-gray-600 mb-1">เบอร์โทร</div>
|
||||
<div class="text-lg text-gray-900">{{ profile.phone || '-' }}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="text-sm text-gray-600 mb-1">ตำแหน่ง</div>
|
||||
<div class="text-lg text-gray-900">
|
||||
<q-badge color="primary">{{ getRoleLabel(profile.role) }}</q-badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="text-sm text-gray-600 mb-1">วันที่สมัคร</div>
|
||||
<div class="text-lg text-gray-900">{{ formatDate(profile.createdAt) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex gap-3 mt-6">
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="แก้ไขโปรไฟล์"
|
||||
icon="edit"
|
||||
@click="showEditModal = true"
|
||||
/>
|
||||
<q-btn
|
||||
outline
|
||||
color="grey-7"
|
||||
label="เปลี่ยนรหัสผ่าน"
|
||||
icon="lock"
|
||||
@click="showPasswordModal = true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</AppCard>
|
||||
|
||||
<!-- Stats Cards
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-5 mt-5">
|
||||
<AppCard>
|
||||
<div class="text-center py-4">
|
||||
<div class="text-4xl font-bold text-primary-600 mb-2">{{ stats.totalCourses }}</div>
|
||||
<div class="text-gray-600">หลักสูตรที่สร้าง</div>
|
||||
</div>
|
||||
</AppCard>
|
||||
|
||||
<AppCard>
|
||||
<div class="text-center py-4">
|
||||
<div class="text-4xl font-bold text-secondary-600 mb-2">{{ stats.totalStudents }}</div>
|
||||
<div class="text-gray-600">ผู้เรียนทั้งหมด</div>
|
||||
</div>
|
||||
</AppCard>
|
||||
</div> -->
|
||||
|
||||
<!-- Edit Profile Modal -->
|
||||
<q-dialog v-model="showEditModal" persistent>
|
||||
<q-card style="min-width: 500px">
|
||||
<q-card-section class="row items-center q-pb-none">
|
||||
<div class="text-h6">แก้ไขโปรไฟล์</div>
|
||||
<q-space />
|
||||
<q-btn icon="close" flat round dense @click="showEditModal = false" />
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section>
|
||||
<q-form @submit="handleUpdateProfile">
|
||||
<q-input
|
||||
v-model="editForm.fullName"
|
||||
label="ชื่อ-นามสกุล"
|
||||
outlined
|
||||
class="mb-4"
|
||||
:rules="[val => !!val || 'กรุณากรอกชื่อ-นามสกุล']"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="person" />
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<q-input
|
||||
v-model="editForm.email"
|
||||
label="อีเมล"
|
||||
type="email"
|
||||
outlined
|
||||
class="mb-4"
|
||||
:rules="[val => !!val || 'กรุณากรอกอีเมล']"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="email" />
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<q-input
|
||||
v-model="editForm.username"
|
||||
label="Username"
|
||||
outlined
|
||||
class="mb-4"
|
||||
:rules="[val => !!val || 'กรุณากรอก username']"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="account_circle" />
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<q-input
|
||||
v-model="editForm.phone"
|
||||
label="เบอร์โทร"
|
||||
outlined
|
||||
class="mb-4"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="phone" />
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<div class="flex justify-end gap-2 mt-4">
|
||||
<q-btn
|
||||
flat
|
||||
label="ยกเลิก"
|
||||
color="grey-7"
|
||||
@click="showEditModal = false"
|
||||
/>
|
||||
<q-btn
|
||||
type="submit"
|
||||
label="บันทึก"
|
||||
color="primary"
|
||||
:loading="saving"
|
||||
/>
|
||||
</div>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<!-- Change Password Modal -->
|
||||
<q-dialog v-model="showPasswordModal" persistent>
|
||||
<q-card style="min-width: 500px">
|
||||
<q-card-section class="row items-center q-pb-none">
|
||||
<div class="text-h6">เปลี่ยนรหัสผ่าน</div>
|
||||
<q-space />
|
||||
<q-btn icon="close" flat round dense @click="showPasswordModal = false" />
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section>
|
||||
<q-form @submit="handleChangePassword">
|
||||
<q-input
|
||||
v-model="passwordForm.currentPassword"
|
||||
label="รหัสผ่านปัจจุบัน"
|
||||
:type="showCurrentPassword ? 'text' : 'password'"
|
||||
outlined
|
||||
class="mb-4"
|
||||
:rules="[val => !!val || 'กรุณากรอกรหัสผ่านปัจจุบัน']"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="lock" />
|
||||
</template>
|
||||
<template v-slot:append>
|
||||
<q-icon
|
||||
:name="showCurrentPassword ? 'visibility_off' : 'visibility'"
|
||||
class="cursor-pointer"
|
||||
@click="showCurrentPassword = !showCurrentPassword"
|
||||
/>
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<q-input
|
||||
v-model="passwordForm.newPassword"
|
||||
label="รหัสผ่านใหม่"
|
||||
:type="showNewPassword ? 'text' : 'password'"
|
||||
outlined
|
||||
class="mb-4"
|
||||
:rules="[
|
||||
val => !!val || 'กรุณากรอกรหัสผ่านใหม่',
|
||||
val => val.length >= 6 || 'รหัสผ่านต้องมีอย่างน้อย 6 ตัวอักษร'
|
||||
]"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="lock" />
|
||||
</template>
|
||||
<template v-slot:append>
|
||||
<q-icon
|
||||
:name="showNewPassword ? 'visibility_off' : 'visibility'"
|
||||
class="cursor-pointer"
|
||||
@click="showNewPassword = !showNewPassword"
|
||||
/>
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<q-input
|
||||
v-model="passwordForm.confirmPassword"
|
||||
label="ยืนยันรหัสผ่านใหม่"
|
||||
:type="showConfirmPassword ? 'text' : 'password'"
|
||||
outlined
|
||||
class="mb-4"
|
||||
:rules="[
|
||||
val => !!val || 'กรุณายืนยันรหัสผ่าน',
|
||||
val => val === passwordForm.newPassword || 'รหัสผ่านไม่ตรงกัน'
|
||||
]"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="lock" />
|
||||
</template>
|
||||
<template v-slot:append>
|
||||
<q-icon
|
||||
:name="showConfirmPassword ? 'visibility_off' : 'visibility'"
|
||||
class="cursor-pointer"
|
||||
@click="showConfirmPassword = !showConfirmPassword"
|
||||
/>
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<div class="flex justify-end gap-2 mt-4">
|
||||
<q-btn
|
||||
flat
|
||||
label="ยกเลิก"
|
||||
color="grey-7"
|
||||
@click="showPasswordModal = false"
|
||||
/>
|
||||
<q-btn
|
||||
type="submit"
|
||||
label="เปลี่ยนรหัสผ่าน"
|
||||
color="primary"
|
||||
:loading="changingPassword"
|
||||
/>
|
||||
</div>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useQuasar } from 'quasar';
|
||||
|
||||
definePageMeta({
|
||||
layout: 'instructor',
|
||||
middleware: 'auth'
|
||||
});
|
||||
|
||||
const $q = useQuasar();
|
||||
const authStore = useAuthStore();
|
||||
|
||||
// Profile data
|
||||
const profile = ref({
|
||||
fullName: 'อาจารย์ทดสอบ ระบบอีเลินนิ่ง',
|
||||
email: 'instructor@example.com',
|
||||
username: 'instructor_test',
|
||||
phone: '081-234-5678',
|
||||
role: 'INSTRUCTOR',
|
||||
avatar: '👨🏫',
|
||||
createdAt: '2024-01-01'
|
||||
});
|
||||
|
||||
const stats = ref({
|
||||
totalCourses: 5,
|
||||
totalStudents: 125
|
||||
});
|
||||
|
||||
// Edit form
|
||||
const showEditModal = ref(false);
|
||||
const saving = ref(false);
|
||||
const editForm = ref({
|
||||
fullName: '',
|
||||
email: '',
|
||||
username: '',
|
||||
phone: ''
|
||||
});
|
||||
|
||||
// Password form
|
||||
const showPasswordModal = ref(false);
|
||||
const changingPassword = ref(false);
|
||||
const showCurrentPassword = ref(false);
|
||||
const showNewPassword = ref(false);
|
||||
const showConfirmPassword = ref(false);
|
||||
const passwordForm = ref({
|
||||
currentPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: ''
|
||||
});
|
||||
|
||||
// Methods
|
||||
const getRoleLabel = (role: string) => {
|
||||
const labels: Record<string, string> = {
|
||||
INSTRUCTOR: 'ผู้สอน',
|
||||
ADMIN: 'ผู้ดูแลระบบ',
|
||||
STUDENT: 'ผู้เรียน'
|
||||
};
|
||||
return labels[role] || role;
|
||||
};
|
||||
|
||||
const formatDate = (date: string) => {
|
||||
return new Date(date).toLocaleDateString('th-TH', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
});
|
||||
};
|
||||
|
||||
const handleAvatarUpload = () => {
|
||||
$q.notify({
|
||||
type: 'info',
|
||||
message: 'ฟีเจอร์อัพโหลดรูปภาพจะพร้อมใช้งานเร็วๆ นี้',
|
||||
position: 'top'
|
||||
});
|
||||
};
|
||||
|
||||
const handleUpdateProfile = async () => {
|
||||
saving.value = true;
|
||||
|
||||
try {
|
||||
// TODO: Call API to update profile
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// Update local data
|
||||
profile.value = { ...profile.value, ...editForm.value };
|
||||
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: 'อัพเดทโปรไฟล์สำเร็จ',
|
||||
position: 'top'
|
||||
});
|
||||
|
||||
showEditModal.value = false;
|
||||
} catch (error) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: 'เกิดข้อผิดพลาด กรุณาลองใหม่อีกครั้ง',
|
||||
position: 'top'
|
||||
});
|
||||
} finally {
|
||||
saving.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleChangePassword = async () => {
|
||||
changingPassword.value = true;
|
||||
|
||||
try {
|
||||
// TODO: Call API to change password
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: 'เปลี่ยนรหัสผ่านสำเร็จ',
|
||||
position: 'top'
|
||||
});
|
||||
|
||||
showPasswordModal.value = false;
|
||||
passwordForm.value = {
|
||||
currentPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: ''
|
||||
};
|
||||
} catch (error) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: 'รหัสผ่านปัจจุบันไม่ถูกต้อง',
|
||||
position: 'top'
|
||||
});
|
||||
} finally {
|
||||
changingPassword.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Watch edit modal
|
||||
watch(showEditModal, (newVal) => {
|
||||
if (newVal) {
|
||||
editForm.value = {
|
||||
fullName: profile.value.fullName,
|
||||
email: profile.value.email,
|
||||
username: profile.value.username,
|
||||
phone: profile.value.phone
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
<template>
|
||||
<div class="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-blue-100">
|
||||
<q-card class="w-full max-w-md p-8 shadow-xl">
|
||||
<div class=" p-6 items-center justify-center">
|
||||
<q-card-section>
|
||||
<div class="text-center mb-8">
|
||||
<h1 class="text-3xl font-bold text-gray-900">E-Learning</h1>
|
||||
|
|
@ -36,6 +35,12 @@
|
|||
/>
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<q-checkbox v-model="rememberMe" label="จดจำฉันไว้" />
|
||||
<a href="#" class="text-sm text-primary-600 hover:text-primary-700">ลืมรหัสผ่าน?</a>
|
||||
</div>
|
||||
|
||||
<q-btn
|
||||
type="submit"
|
||||
color="primary"
|
||||
|
|
@ -46,12 +51,12 @@
|
|||
/>
|
||||
</q-form>
|
||||
<div class="mt-6 text-center text-sm text-gray-600">
|
||||
<p>ทดสอบ: instructor@test.com / admin@test.com</p>
|
||||
<p>ทดสอบ: admin@elearning.local / instructor@elearning.local</p>
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useQuasar } from 'quasar';
|
||||
definePageMeta({
|
||||
|
|
@ -63,6 +68,7 @@ const router = useRouter();
|
|||
const email = ref('');
|
||||
const password = ref('');
|
||||
const showPassword = ref(false);
|
||||
const rememberMe = ref(false);
|
||||
const loading = ref(false);
|
||||
const handleLogin = async () => {
|
||||
loading.value = true;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue