elearning/frontend_management/pages/instructor/profile/index.vue
2026-01-14 13:58:25 +07:00

419 lines
13 KiB
Vue

<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>