feat: Introduce core authentication service, several new admin management pages, and instructor feature tests.
All checks were successful
Build and Deploy Frontend Management to Dev Server / Build Frontend Management Docker Image (push) Successful in 52s
Build and Deploy Frontend Management to Dev Server / Deploy E-learning Frontend Management to Dev Server (push) Successful in 4s
Build and Deploy Frontend Management to Dev Server / Notify Deployment Status (push) Successful in 1s
All checks were successful
Build and Deploy Frontend Management to Dev Server / Build Frontend Management Docker Image (push) Successful in 52s
Build and Deploy Frontend Management to Dev Server / Deploy E-learning Frontend Management to Dev Server (push) Successful in 4s
Build and Deploy Frontend Management to Dev Server / Notify Deployment Status (push) Successful in 1s
This commit is contained in:
parent
000f9eea5c
commit
0205aab461
11 changed files with 818 additions and 121 deletions
|
|
@ -168,7 +168,7 @@
|
|||
<q-badge :color="getActionColor(selectedLog.action)">{{ selectedLog.action }}</q-badge>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-subtitle2 text-grey">Time</div>
|
||||
<div class="text-subtitle2 text-grey">Date & Time</div>
|
||||
<div>{{ formatDate(selectedLog.created_at) }}</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -291,7 +291,7 @@ const columns = [
|
|||
{ name: 'entity_type', label: 'Entity Type', field: 'entity_type', align: 'left' },
|
||||
{ name: 'entity_id', label: 'Entity ID', field: 'entity_id', align: 'left' },
|
||||
|
||||
{ name: 'created_at', label: 'Time', field: 'created_at', align: 'left' },
|
||||
{ name: 'created_at', label: 'Date & Time', field: 'created_at', align: 'left' },
|
||||
{ name: 'actions', label: '', field: 'actions', align: 'center' }
|
||||
];
|
||||
|
||||
|
|
@ -421,13 +421,23 @@ const formatDate = (date: string) => {
|
|||
return new Date(date).toLocaleString('th-TH');
|
||||
};
|
||||
|
||||
const ACTION_COLOR_MAP: Record<string, string> = {
|
||||
DELETE: 'negative',
|
||||
REJECT: 'negative',
|
||||
DEACTIVATE: 'negative',
|
||||
ERROR: 'negative',
|
||||
UPDATE: 'warning',
|
||||
CHANGE: 'warning',
|
||||
CREATE: 'positive',
|
||||
APPROVE: 'positive',
|
||||
ACTIVATE: 'positive',
|
||||
LOGIN: 'info',
|
||||
};
|
||||
|
||||
const getActionColor = (action: string) => {
|
||||
if (!action) return 'grey';
|
||||
if (action.includes('DELETE') || action.includes('REJECT') || action.includes('DEACTIVATE') || action.includes('ERROR')) return 'negative';
|
||||
if (action.includes('UPDATE') || action.includes('CHANGE')) return 'warning';
|
||||
if (action.includes('CREATE') || action.includes('APPROVE') || action.includes('ACTIVATE')) return 'positive';
|
||||
if (action.includes('LOGIN')) return 'info';
|
||||
return 'grey-8';
|
||||
if (!action) return 'grey';
|
||||
const keyword = Object.keys(ACTION_COLOR_MAP).find((key) => action.includes(key));
|
||||
return keyword ? ACTION_COLOR_MAP[keyword] : 'grey-8';
|
||||
};
|
||||
|
||||
// Check for deep link to detail
|
||||
|
|
|
|||
|
|
@ -307,8 +307,17 @@ const handleSave = async () => {
|
|||
const confirmDelete = (category: CategoryResponse) => {
|
||||
$q.dialog({
|
||||
title: 'ยืนยันการลบ',
|
||||
message: `คุณต้องการลบหมวดหมู่ "${category.name.th}" หรือไม่?`,
|
||||
cancel: true,
|
||||
message: `คุณต้องการลบหมวดหมู่ "${category.name.th}" หรือไม่?<br><span style="color: red;">การลบหมวดหมู่นี้จะทำให้หมวดหมู่ถูกลบออกจากหลักสูตรทั้งหมดที่ใช้งานอยู่</span>`,
|
||||
html: true,
|
||||
cancel: {
|
||||
label: 'ยกเลิก',
|
||||
color: 'grey',
|
||||
flat: true
|
||||
},
|
||||
ok: {
|
||||
label: 'ลบหมวดหมู่',
|
||||
color: 'negative'
|
||||
},
|
||||
persistent: true
|
||||
}).onOk(async () => {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@
|
|||
<div class="p-6">
|
||||
<div class="flex flex-wrap gap-2 mb-4">
|
||||
<q-badge :color="getStatusColor(course.status)" :label="getStatusLabel(course.status)" />
|
||||
<q-badge color="grey" :label="course.category.name.th" />
|
||||
<q-badge color="grey" :label="course.category?.name?.th || 'ไม่มีหมวดหมู่'" />
|
||||
<q-badge v-if="course.is_free" color="green" label="ฟรี" />
|
||||
<q-badge v-else color="blue" :label="`฿${course.price.toLocaleString()}`" />
|
||||
<q-badge v-if="course.have_certificate" color="purple" label="มีใบประกาศนียบัตร" />
|
||||
|
|
|
|||
|
|
@ -153,7 +153,8 @@
|
|||
<!-- Category -->
|
||||
<div class="bg-gray-50 p-4 rounded-lg gap-2">
|
||||
<div class="font-bold mb-2">หมวดหมู่ (Category):</div>
|
||||
<div class="text-gray-700 mb-2">{{ selectedCourse.category.name.th }} ({{ selectedCourse.category.name.en }})</div>
|
||||
<div v-if="selectedCourse.category" class="text-gray-700 mb-2">{{ selectedCourse.category.name.th }} ({{ selectedCourse.category.name.en }})</div>
|
||||
<div v-else class="text-gray-400 italic mb-2">ไม่มีหมวดหมู่</div>
|
||||
</div>
|
||||
|
||||
<!-- Instructors -->
|
||||
|
|
@ -262,7 +263,7 @@ const columns = [
|
|||
field: (row: RecommendedCourse) => row.instructors?.find((i: any) => i.is_primary)?.user.username || '',
|
||||
align: 'left' as const
|
||||
},
|
||||
{ name: 'category', label: 'Category', field: (row: RecommendedCourse) => row.category.name.th, sortable: true, align: 'left' as const },
|
||||
{ name: 'category', label: 'Category', field: (row: RecommendedCourse) => row.category?.name?.th || 'ไม่มีหมวดหมู่', sortable: true, align: 'left' as const },
|
||||
{ name: 'price', label: 'Price', field: 'price', sortable: true, align: 'right' as const },
|
||||
{ name: 'is_recommended', label: 'Recommended', field: 'is_recommended', sortable: true, align: 'center' as const },
|
||||
{ name: 'actions', label: 'Actions', field: 'actions', align: 'center' as const },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue