ED:Font color

This commit is contained in:
supalerk-ar66 2026-01-14 10:20:06 +07:00
parent d8d3dff2e7
commit 563564ee58
14 changed files with 162 additions and 83 deletions

View file

@ -1 +1 @@
{"id":"dev","timestamp":1768276905519}
{"id":"dev","timestamp":1768360747858}

View file

@ -1 +1 @@
{"id":"dev","timestamp":1768276905519,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
{"id":"dev","timestamp":1768360747858,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}

View file

@ -1,5 +1,5 @@
{
"date": "2026-01-13T04:01:52.330Z",
"date": "2026-01-14T03:19:14.221Z",
"preset": "nitro-dev",
"framework": {
"name": "nuxt",
@ -9,9 +9,9 @@
"nitro": "2.12.8"
},
"dev": {
"pid": 17152,
"pid": 16832,
"workerAddress": {
"socketPath": "\\\\.\\pipe\\nitro-worker-17152-1-1-4801.sock"
"socketPath": "\\\\.\\pipe\\nitro-worker-16832-1-1-6766.sock"
}
}
}

View file

@ -1,7 +1,7 @@
/// <reference types="quasar" />
/// <reference types="@nuxtjs/tailwindcss" />
/// <reference types="nuxt-quasar-ui" />
/// <reference types="@nuxt/devtools" />
/// <reference types="@nuxtjs/tailwindcss" />
/// <reference types="@nuxt/telemetry" />
/// <reference path="types/builder-env.d.ts" />
/// <reference types="nuxt" />

View file

@ -1,4 +1,4 @@
// generated by the @nuxtjs/tailwindcss <https://github.com/nuxt-modules/tailwindcss> module at 13/1/2569 11:47:48
// generated by the @nuxtjs/tailwindcss <https://github.com/nuxt-modules/tailwindcss> module at 14/1/2569 10:19:11
import "@nuxtjs/tailwindcss/config-ctx"
import configMerger from "@nuxtjs/tailwindcss/merger";

View file

@ -69,7 +69,10 @@ const emit = defineEmits<{
{{ level }}
</span>
</div>
<div v-if="price" class="absolute top-4 right-4 glass px-3 py-1 rounded-full text-xs font-black text-white shadow-sm">
<div v-if="price"
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'"
>
{{ price }}
</div>
</div>
@ -107,7 +110,7 @@ const emit = defineEmits<{
</div>
<!-- Actions -->
<button v-if="showViewDetails" class="btn-premium-secondary w-full mt-auto" @click="emit('viewDetails')">
<button v-if="showViewDetails" class="btn-premium-primary w-full mt-auto dark:!text-white" @click="emit('viewDetails')">
รายละเอยด
</button>
@ -116,7 +119,7 @@ const emit = defineEmits<{
</NuxtLink>
<div v-if="completed && (showCertificate || showStudyAgain)" class="flex flex-col gap-2 mt-auto">
<NuxtLink v-if="showStudyAgain" to="/classroom/learning" class="btn-premium-secondary w-full">
<NuxtLink v-if="showStudyAgain" to="/classroom/learning" class="btn-premium-primary w-full dark:!text-white">
ทบทวนบทเรยน
</NuxtLink>
<button v-if="showCertificate" class="btn-premium-success w-full shadow-lg shadow-emerald-600/20" @click="emit('viewCertificate')">
@ -172,6 +175,7 @@ const emit = defineEmits<{
font-size: 0.875rem;
border: 1px solid var(--border-color);
transition: all 0.3s ease;
text-align: center;
}
.btn-premium-secondary:hover {
background: var(--bg-body);
@ -180,14 +184,15 @@ const emit = defineEmits<{
}
:global(.dark) .btn-premium-secondary {
background: rgba(255, 255, 255, 0.05);
color: #e2e8f0;
border-color: rgba(255, 255, 255, 0.1);
background: rgba(34, 211, 238, 0.1);
color: #22d3ee !important;
border-color: rgba(34, 211, 238, 0.3) !important;
}
:global(.dark) .btn-premium-secondary:hover {
background: rgba(255, 255, 255, 0.1);
border-color: rgba(255, 255, 255, 0.2);
background: rgba(34, 211, 238, 0.2);
border-color: #22d3ee !important;
color: #67e8f9 !important;
}
.btn-premium-success {

View file

@ -94,7 +94,7 @@ const filteredCourses = computed(() => {
<div v-if="!showDetail">
<!-- Search & Filters Header -->
<div class="flex justify-between items-center mb-6" style="flex-wrap: wrap; gap: 16px;">
<h1 style="font-size: 28px; font-weight: 700; color: #000000;">รายการคอรสทงหมด</h1>
<h1 class="text-[28px] font-bold text-slate-900 dark:text-white">รายการคอรสทงหมด</h1>
<div class="flex gap-3" style="flex-wrap: wrap;">
<!-- Search Input -->
<div class="relative">
@ -212,7 +212,7 @@ const filteredCourses = computed(() => {
</div>
</div>
<h1 style="font-size: 32px; font-weight: 700; margin-bottom: 16px; color: #000000;">เบองตนการออกแบบ UX/UI</h1>
<h1 class="text-[32px] font-bold mb-4 text-slate-900 dark:text-white">เบองตนการออกแบบ UX/UI</h1>
<p class="text-slate-700 dark:text-slate-400 mb-6" style="font-size: 1.1em; line-height: 1.7;">
เนอหาครอบคลมทกอยางตงแตการวยผใช (User Research) ไปจนถงการทำตนแบบความละเอยดส (High-fidelity Prototyping)
เหมาะสำหรบผเรมตนทองการเขาสสายงานออกแบบผลตภณฑ
@ -220,7 +220,7 @@ const filteredCourses = computed(() => {
<!-- Learning Objectives -->
<div class="card mb-6">
<h3 class="font-bold mb-4" style="color: #000000;">งทณจะไดเรยนร</h3>
<h3 class="font-bold mb-4 text-slate-900 dark:text-white">งทณจะไดเรยนร</h3>
<ul class="grid-12" style="grid-template-columns: 1fr 1fr; gap: 12px;">
<li class="flex gap-2 text-sm"><span style="color: var(--success);"></span> การวยผใช (User Research)</li>
<li class="flex gap-2 text-sm"><span style="color: var(--success);"></span> การวาดโครงรางและทำตนแบบ</li>
@ -231,11 +231,11 @@ const filteredCourses = computed(() => {
<!-- Course Syllabus / Outline -->
<div class="card">
<h3 class="font-bold mb-4" style="color: #000000;">เนอหาในคอร</h3>
<h3 class="font-bold mb-4 text-slate-900 dark:text-white">เนอหาในคอร</h3>
<!-- Chapter 1 -->
<div class="mb-4">
<div class="flex justify-between p-4 rounded mb-2" style="background: #f3f4f6; border: 1px solid #e5e7eb;">
<span class="font-bold" style="color: #000000;">01. บทนำ</span>
<span class="font-bold text-slate-900 dark:text-slate-900">01. บทนำ</span>
<span class="text-sm text-slate-600 dark:text-slate-400">3 บทเรยน</span>
</div>
<div style="padding-left: 16px;">

View file

@ -48,8 +48,8 @@ const chapters = [
{
title: '02. วิธีการวิจัย',
lessons: [
{ id: '2.1', title: 'การสัมภาษณ์ผู้ใช้', icon: '🔒', status: 'locked' },
{ id: '2.2', title: 'การสร้าง Persona', icon: '🔒', status: 'locked' },
{ id: '2.1', title: 'การสัมภาษณ์ผู้ใช้', icon: '', status: 'locked' },
{ id: '2.2', title: 'การสร้าง Persona', icon: '', status: 'locked' },
]
}
]
@ -93,12 +93,12 @@ const seek = (e: MouseEvent) => {
</script>
<template>
<div class="learning-shell font-main antialiased selection:bg-blue-500/30">
<div class="learning-shell font-main antialiased selection:bg-blue-500/30 dark:!bg-[#0F172A] dark:!text-slate-200 transition-colors">
<!-- Header: Custom top bar for learning context -->
<header class="learning-header px-2 md:px-4 h-14 md:h-[56px] border-b border-white/5 flex items-center justify-between gap-2 md:gap-4">
<header class="learning-header px-2 md:px-4 h-14 md:h-[56px] border-b border-slate-200 dark:border-white/5 flex items-center justify-between gap-2 md:gap-4 dark:!bg-slate-800 transition-colors">
<div class="flex items-center gap-1 md:gap-6 min-w-0 flex-1">
<!-- Mobile Sidebar Toggle -->
<button class="md:hidden text-white p-2 hover:bg-white/5 rounded-lg flex-shrink-0" @click="toggleSidebar">
<button class="md:hidden text-slate-900 dark:text-white p-2 hover:bg-slate-100 dark:hover:bg-white/5 rounded-lg flex-shrink-0 transition-colors" @click="toggleSidebar">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" /></svg>
</button>
<!-- Back Navigation -->
@ -106,7 +106,7 @@ const seek = (e: MouseEvent) => {
<span class="text-lg md:text-base"></span>
<span class="hidden md:inline text-[11px] font-bold">กลบไปหนาหล</span>
</NuxtLink>
<div class="w-[1px] h-4 bg-white/10 hidden md:block flex-shrink-0"/>
<div class="w-[1px] h-4 bg-slate-200 dark:bg-white/10 hidden md:block flex-shrink-0"/>
<h1 class="text-[13px] md:text-sm font-black text-slate-900 dark:text-white tracking-tight truncate min-w-0 pr-2">เบองตนการออกแบบ UX/UI</h1>
</div>
@ -124,7 +124,7 @@ const seek = (e: MouseEvent) => {
</header>
<!-- Sidebar: Course Curriculum list -->
<aside class="learning-sidebar" :class="{ 'open': sidebarOpen }">
<aside class="learning-sidebar dark:!bg-gray-900 dark:!border-r-white/5 transition-colors" :class="{ 'open': sidebarOpen }">
<div class="py-2">
<!-- Announcements Tab Trigger -->
<div
@ -134,17 +134,17 @@ const seek = (e: MouseEvent) => {
>
<div class="flex items-center gap-3">
<span class="text-lg" style="color: #ff3366;">📢</span>
<span class="font-black text-[12px] tracking-tight">ประกาศในคอร</span>
<span class="font-black text-[12px] tracking-tight dark:!text-white">ประกาศในคอร</span>
</div>
</div>
<!-- Chapters & Lessons List -->
<div v-for="chapter in chapters" :key="chapter.title" class="mt-4">
<div class="chapter-header px-4 py-2">{{ chapter.title }}</div>
<div class="chapter-header px-4 py-2 dark:!bg-slate-900 dark:!text-white dark:!border-b-white/5">{{ chapter.title }}</div>
<div
v-for="lesson in chapter.lessons"
:key="lesson.id"
class="lesson-item px-4"
class="lesson-item px-4 dark:!text-slate-300 dark:!border-b-white/5 hover:dark:!bg-white/5 hover:dark:!text-white transition-colors"
:class="{
'active-lesson': currentLessonId === lesson.id && activeTab === 'details',
'completed': lesson.status === 'completed',
@ -161,7 +161,7 @@ const seek = (e: MouseEvent) => {
<!-- Exam Link -->
<div class="mt-8 border-t border-white/5 pt-2">
<div class="chapter-header px-4 py-2 uppercase tracking-widest text-[10px]">03. แบบทดสอบทายบท</div>
<div class="chapter-header px-4 py-2 uppercase tracking-widest text-[10px] dark:!bg-slate-900 dark:!text-white dark:!border-b-white/5">03. แบบทดสอบทายบท</div>
<NuxtLink to="/classroom/quiz" class="lesson-item px-4 no-underline cursor-pointer">
<span class="text-[12px] font-medium text-slate-900 dark:text-slate-200 group-hover:text-black dark:group-hover:text-white transition-colors">อสอบปลายภาค</span>
<span class="text-xs opacity-50">📄</span>
@ -174,7 +174,7 @@ const seek = (e: MouseEvent) => {
<div v-if="sidebarOpen" class="fixed inset-0 bg-black/60 backdrop-blur-sm z-[85] md:hidden" @click="toggleSidebar"/>
<!-- Main View Area -->
<div class="main-container custom-scrollbar overflow-x-hidden pt-6">
<div class="main-container custom-scrollbar overflow-x-hidden pt-6 dark:!bg-[#0B0F1A] transition-colors">
<main class="w-full max-w-7xl mx-auto px-4 md:px-8 pb-10 md:pb-20">
<!-- Tab Content: Announcements (Center Aligned) -->
<div v-if="activeTab === 'announcements'" class="animate-fade-in max-w-4xl mx-auto space-y-8 pt-8 md:pt-14">
@ -243,21 +243,21 @@ const seek = (e: MouseEvent) => {
</div>
<!-- Lesson Notes Card -->
<div class="rounded-2xl bg-white dark:bg-slate-800/60 border border-slate-200 dark:border-slate-700 p-6 md:p-10 shadow-sm dark:shadow-xl transition-colors">
<h3 class="text-[11px] md:text-[12px] font-black text-slate-900 dark:text-slate-100 mb-6 uppercase tracking-[0.2em] border-b border-slate-200 dark:border-slate-700 pb-4">นทกบทเรยน</h3>
<div class="text-[15px] md:text-[16px] text-slate-700 dark:text-slate-200 leading-relaxed font-medium space-y-6">
<div class="rounded-2xl bg-white dark:!bg-slate-800 border border-slate-200 dark:border-slate-700 p-6 md:p-10 shadow-sm dark:shadow-xl transition-colors">
<h3 class="text-[14px] md:text-[16px] font-black text-slate-900 dark:text-slate-50 mb-6 uppercase tracking-[0.2em] border-b border-slate-200 dark:border-slate-600 pb-4">นทกบทเรยน</h3>
<div class="text-[16px] md:text-[18px] text-slate-700 dark:text-slate-200 leading-relaxed font-medium space-y-6">
<p>การ Wireframe อการจำลองโครงสรางพนฐานของหนาจอ (Layout) โดยเนนไปทการจดวางตำแหนงปมและเนอหาสำคญเพอวางโครงสรางกอนลงมอดไซนจร</p>
<div class="bg-slate-50 dark:bg-slate-800/40 border border-slate-200 dark:border-slate-700 border-l-4 border-l-blue-500 p-6 rounded-r-2xl">
<div class="font-black text-blue-700 dark:text-blue-400 text-[12px] uppercase tracking-wider mb-3">ประเดนสำค:</div>
<div class="bg-slate-50 dark:bg-slate-700/50 border border-slate-200 dark:border-slate-600 border-l-4 border-l-blue-500 p-6 rounded-r-2xl">
<div class="font-black text-blue-700 dark:text-blue-300 text-[14px] md:text-[16px] uppercase tracking-wider mb-3">ประเดนสำค:</div>
<ul class="space-y-4">
<li class="flex gap-4 items-start">
<span class="w-1.5 h-1.5 rounded-full bg-blue-500 mt-2 flex-shrink-0"/>
<span class="text-slate-700 dark:text-slate-300">ความละเอยดต (Low-fidelity) วยใหโฟกสทการใชงาน (Functionality) เปนหล</span>
<span class="w-1.5 h-1.5 rounded-full bg-blue-500 mt-2.5 flex-shrink-0"/>
<span class="text-slate-700 dark:text-slate-100">ความละเอยดต (Low-fidelity) วยใหโฟกสทการใชงาน (Functionality) เปนหล</span>
</li>
<li class="flex gap-4 items-start">
<span class="w-1.5 h-1.5 rounded-full bg-blue-500 mt-2 flex-shrink-0"/>
<span class="text-slate-700 dark:text-slate-300">วยในการสอสารไอเดยก Stakeholders ใหเหนภาพตรงก</span>
<span class="w-1.5 h-1.5 rounded-full bg-blue-500 mt-2.5 flex-shrink-0"/>
<span class="text-slate-700 dark:text-slate-100">วยในการสอสารไอเดยก Stakeholders ใหเหนภาพตรงก</span>
</li>
</ul>
</div>
@ -268,27 +268,27 @@ const seek = (e: MouseEvent) => {
<!-- Right Side: Resources + Actions (4/12) -->
<div class="md:col-span-4 space-y-6 md:sticky md:top-6">
<!-- Resources Card -->
<div class="rounded-2xl bg-white dark:bg-slate-800/60 border border-slate-200 dark:border-slate-700 p-6 md:p-8 shadow-sm dark:shadow-xl transition-colors">
<h3 class="text-[11px] md:text-[12px] font-black text-slate-900 dark:text-slate-100 mb-6 uppercase tracking-[0.2em] border-b border-slate-200 dark:border-slate-700 pb-4">เอกสารประกอบ</h3>
<div class="rounded-2xl bg-white dark:!bg-slate-800 border border-slate-200 dark:border-slate-700 p-6 md:p-8 shadow-sm dark:shadow-xl transition-colors">
<h3 class="text-[14px] md:text-[16px] font-black text-slate-900 dark:text-slate-100 mb-6 uppercase tracking-[0.2em] border-b border-slate-200 dark:border-slate-700 pb-4">เอกสารประกอบ</h3>
<div class="space-y-3">
<!-- Attachment Row -->
<div class="flex items-center justify-between p-4 bg-slate-50 dark:bg-slate-800/40 rounded-2xl border border-slate-200 dark:border-slate-700 group hover:bg-slate-100 dark:hover:bg-slate-700/40 transition-all cursor-pointer min-w-0">
<div class="flex items-center justify-between p-4 bg-slate-50 dark:bg-slate-700/50 rounded-2xl border border-slate-200 dark:border-slate-600 group hover:bg-slate-100 dark:hover:bg-slate-600/50 transition-all cursor-pointer min-w-0">
<div class="flex items-center gap-3 min-w-0 flex-1">
<span class="text-xl flex-shrink-0">📄</span>
<div class="flex flex-col min-w-0">
<span class="text-[12px] font-bold text-slate-800 dark:text-slate-100 truncate pr-2">สไลดประกอบการสอน.pdf</span>
<span class="text-[9px] font-black text-slate-500 dark:text-slate-400 uppercase">2.4 MB</span>
<span class="text-[14px] font-bold text-slate-800 dark:text-slate-100 truncate pr-2">สไลดประกอบการสอน.pdf</span>
<span class="text-[11px] font-black text-slate-500 dark:text-slate-400 uppercase">2.4 MB</span>
</div>
</div>
<button class="w-8 h-8 rounded-full flex items-center justify-center bg-slate-100 dark:bg-slate-700/50 group-hover:bg-blue-600 text-slate-600 dark:text-slate-400 group-hover:text-white transition-all text-xs flex-shrink-0"></button>
</div>
<!-- Attachment Row -->
<div class="flex items-center justify-between p-4 bg-slate-50 dark:bg-slate-800/40 rounded-2xl border border-slate-200 dark:border-slate-700 group hover:bg-slate-100 dark:hover:bg-slate-700/40 transition-all cursor-pointer min-w-0">
<div class="flex items-center justify-between p-4 bg-slate-50 dark:bg-slate-700/50 rounded-2xl border border-slate-200 dark:border-slate-600 group hover:bg-slate-100 dark:hover:bg-slate-600/50 transition-all cursor-pointer min-w-0">
<div class="flex items-center gap-3 min-w-0 flex-1">
<span class="text-xl flex-shrink-0">📁</span>
<div class="flex flex-col min-w-0">
<span class="text-[12px] font-bold text-slate-800 dark:text-slate-100 truncate pr-2">ไฟลแบบฝกห.zip</span>
<span class="text-[9px] font-black text-slate-500 dark:text-slate-400 uppercase">15 MB</span>
<span class="text-[14px] font-bold text-slate-800 dark:text-slate-100 truncate pr-2">ไฟลแบบฝกห.zip</span>
<span class="text-[11px] font-black text-slate-500 dark:text-slate-400 uppercase">15 MB</span>
</div>
</div>
<button class="w-8 h-8 rounded-full flex items-center justify-center bg-slate-100 dark:bg-slate-700/50 group-hover:bg-blue-600 text-slate-600 dark:text-slate-400 group-hover:text-white transition-all text-xs flex-shrink-0"></button>

View file

@ -66,7 +66,7 @@ onUnmounted(() => {
</script>
<template>
<div class="quiz-shell min-h-screen bg-white dark:bg-[#0b0f1a] text-slate-900 dark:text-slate-200 antialiased selection:bg-blue-500/20 transition-colors">
<div class="quiz-shell min-h-screen bg-white dark:bg-[#0b0f1a] text-slate-900 dark:text-slate-200 font-main antialiased selection:bg-blue-500/20 transition-colors">
<!-- Header: Precise matching of the image -->
<header class="h-14 bg-white dark:bg-[#161b22] fixed top-0 inset-x-0 z-[100] flex items-center px-6 border-b border-slate-300 dark:border-white/5 transition-colors">
<div class="flex items-center">

View file

@ -20,7 +20,7 @@ useHead({
<template>
<div>
<!-- Page Header -->
<h1 style="font-size: 28px; font-weight: 700; margin-bottom: 24px;">ประกาศ</h1>
<h1 class="text-[28px] font-bold mb-6 text-slate-900 dark:text-white">ประกาศ</h1>
<!--
Main Layout: 12-column Grid
@ -40,7 +40,7 @@ useHead({
<span class="status-pill status-warning">สำค</span>
<span class="text-sm text-slate-600 dark:text-slate-400">24 .. 2024</span>
</div>
<h2 class="font-bold mb-4" style="font-size: 1.25rem;">แจงปดปรบปรงระบบ</h2>
<h2 class="text-xl font-bold mb-4 text-slate-900 dark:text-white">แจงปดปรบปรงระบบ</h2>
<p class="mb-4">เราจะทำการปดปรบปรงระบบในวนท 25 .. เวลา 02:00 - 04:00 . ขออภยในความไมสะดวก</p>
<!-- Attachment Block -->
<div class="flex items-center gap-2 p-3 rounded" style="background: var(--neutral-50); border: 1px solid var(--border-color); width: fit-content;">
@ -53,7 +53,7 @@ useHead({
<div class="flex justify-between items-start mb-2" style="flex-wrap: wrap; gap: 8px;">
<div>
<span class="status-pill status-neutral mb-2">เบองตนการออกแบบ UX/UI</span>
<h3 class="font-bold">เรมเปดหลกสตรเดอนมกราคมแล!</h3>
<h3 class="font-bold text-slate-900 dark:text-white">เรมเปดหลกสตรเดอนมกราคมแล!</h3>
</div>
<span class="text-sm text-slate-600 dark:text-slate-400">23 .. 2024</span>
</div>
@ -66,7 +66,7 @@ useHead({
<div class="flex justify-between items-start mb-2" style="flex-wrap: wrap; gap: 8px;">
<div>
<span class="status-pill status-neutral mb-2">การเขาถงเว (WCAG)</span>
<h3 class="font-bold">ดาวนโหลดเอกสารประกอบการเรยนไดแล</h3>
<h3 class="font-bold text-slate-900 dark:text-white">ดาวนโหลดเอกสารประกอบการเรยนไดแล</h3>
</div>
<span class="text-sm text-slate-600 dark:text-slate-400">22 .. 2024</span>
</div>
@ -82,7 +82,7 @@ useHead({
<div class="flex justify-between items-start mb-2" style="flex-wrap: wrap; gap: 8px;">
<div>
<span class="status-pill status-neutral mb-2">ปแบบ React นส</span>
<h3 class="font-bold">ปเดตบทเรยนใหม: React Server Components</h3>
<h3 class="font-bold text-slate-900 dark:text-white">ปเดตบทเรยนใหม: React Server Components</h3>
</div>
<span class="text-sm text-slate-600 dark:text-slate-400">21 .. 2024</span>
</div>
@ -93,7 +93,7 @@ useHead({
<!-- Announcement: General New Course -->
<div class="card mb-4">
<div class="flex justify-between items-start mb-2" style="flex-wrap: wrap; gap: 8px;">
<h3 class="font-bold">คอรสใหม: Advanced Python</h3>
<h3 class="font-bold text-slate-900 dark:text-white">คอรสใหม: Advanced Python</h3>
<span class="text-sm text-slate-600 dark:text-slate-400">20 .. 2024</span>
</div>
<p class="text-slate-700 dark:text-slate-300 mb-2">พบกบคอรสใหมาส เรยนรโครงสรางขอม Python...</p>
@ -103,7 +103,7 @@ useHead({
<!-- Announcement: Platform Update -->
<div class="card mb-4">
<div class="flex justify-between items-start mb-2" style="flex-wrap: wrap; gap: 8px;">
<h3 class="font-bold">นดอนรบสไซนใหม!</h3>
<h3 class="font-bold text-slate-900 dark:text-white">นดอนรบสไซนใหม!</h3>
<span class="text-sm text-slate-600 dark:text-slate-400">15 .. 2024</span>
</div>
<p class="text-slate-700 dark:text-slate-300 mb-2">เราปรบโฉมใหมไฉไลกวาเด เพอการใชงานทงข...</p>
@ -117,7 +117,7 @@ useHead({
========================================== -->
<div class="col-span-4">
<div class="card">
<h3 class="font-bold mb-4">หมวดหม</h3>
<h3 class="font-bold mb-4 text-slate-900 dark:text-white">หมวดหม</h3>
<ul class="flex flex-col gap-2">
<!-- Filter Option: All -->
<li class="flex justify-between items-center p-2 rounded cursor-pointer" style="background: var(--neutral-50);">

View file

@ -101,7 +101,7 @@ const recommendedCourses = [
<!-- Section: Recommended Courses -->
<div class="mb-8">
<h2 class="text-2xl font-black flex items-center gap-3 tracking-tight text-black 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)]"/>
คอรสเรยนแนะนำ
</h2>

View file

@ -71,7 +71,7 @@ const downloadCertificate = () => {
<div>
<!-- Page Header & Filters -->
<div class="flex justify-between items-center mb-6 mobile-stack">
<h1 style="font-size: 28px; font-weight: 700;">คอรสของฉ</h1>
<h1 class="text-[28px] font-bold text-slate-900 dark:text-white">คอรสของฉ</h1>
<!-- Filter Tabs -->
<div class="flex gap-2" style="overflow-x: auto; padding-bottom: 4px; width: 100%; justify-content: flex-start;">
<button

View file

@ -16,6 +16,7 @@ useHead({
})
const { currentUser } = useAuth()
const { errors, validate, clearFieldError } = useFormValidation()
const isEditing = ref(false)
// User Profile Data Management
@ -23,17 +24,37 @@ const userData = ref({
firstName: currentUser.value.firstName,
lastName: currentUser.value.lastName,
email: currentUser.value.email,
phone: '081-234-5678',
phone: '0812345678',
joinDate: '12 ธ.ค. 2024',
studentId: 'STU 68203',
photoURL: '', // Added missing property
prefix: 'นาย' // Added missing property
photoURL: '',
prefix: 'นาย'
})
// Password Form (Separate from userData for security/logic)
const passwordForm = reactive({
currentPassword: '',
newPassword: '',
confirmPassword: ''
})
// Validation Rules
const validationRules = {
firstName: { rules: { required: true }, label: 'ชื่อ' },
lastName: { rules: { required: true }, label: 'นามสกุล' },
email: { rules: { required: true, email: true }, label: 'อีเมล' },
phone: { rules: { required: true, pattern: /^0[0-9]{8,9}$/ }, label: 'เบอร์โทรศัพท์' },
newPassword: { rules: { minLength: 6 }, label: 'รหัสผ่านใหม่' },
confirmPassword: { rules: { match: 'newPassword' }, label: 'ยืนยันรหัสผ่าน' }
}
const fileInput = ref<HTMLInputElement | null>(null)
const toggleEdit = (edit: boolean) => {
isEditing.value = edit
// Clear errors when toggling modes
if(edit === false) {
// Logic to reset form if canceling could go here
}
}
const triggerUpload = () => {
@ -54,9 +75,20 @@ const handleFileUpload = (event: Event) => {
// Save Profile Updates (Mock Implementation)
const saveProfile = () => {
// Combine data for validation
const formData = {
...userData.value,
...passwordForm
}
if (!validate(formData, validationRules)) return
currentUser.value.firstName = userData.value.firstName
currentUser.value.lastName = userData.value.lastName
currentUser.value.email = userData.value.email
// Successful save
alert('บันทึกข้อมูลเรียบร้อยแล้ว')
isEditing.value = false
}
</script>
@ -95,7 +127,7 @@ const saveProfile = () => {
</div>
<div class="pb-2">
<h2 class="text-3xl font-black text-white mb-1">{{ userData.firstName }} {{ userData.lastName }}</h2>
<p class="text-slate-400 font-bold uppercase tracking-widest text-[10px]">Student ID: STU-88293</p>
</div>
</div>
@ -157,7 +189,7 @@ const saveProfile = () => {
<!-- Form Inputs -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-10">
<div class="space-y-2">
<label class="text-xs font-black uppercase tracking-widest text-slate-400">คำนำหน</label>
<label class="text-xs font-black uppercase tracking-widest text-slate-300">คำนำหน</label>
<select v-model="userData.prefix" class="premium-input w-full">
<option>นาย</option>
<option>นาง</option>
@ -166,21 +198,49 @@ const saveProfile = () => {
</div>
<div class="grid grid-cols-2 gap-4">
<div class="space-y-2">
<label class="text-xs font-black uppercase tracking-widest text-slate-400"></label>
<input v-model="userData.firstName" type="text" class="premium-input w-full">
<label class="text-xs font-black uppercase tracking-widest text-slate-300"></label>
<input
v-model="userData.firstName"
type="text"
class="premium-input w-full"
:class="{ '!border-red-500': errors.firstName }"
@input="clearFieldError('firstName')"
>
<span v-if="errors.firstName" class="text-red-500 text-[10px] mt-1 font-bold">{{ errors.firstName }}</span>
</div>
<div class="space-y-2">
<label class="text-xs font-black uppercase tracking-widest text-slate-400">นามสก</label>
<input v-model="userData.lastName" type="text" class="premium-input w-full">
<label class="text-xs font-black uppercase tracking-widest text-slate-300">นามสก</label>
<input
v-model="userData.lastName"
type="text"
class="premium-input w-full"
:class="{ '!border-red-500': errors.lastName }"
@input="clearFieldError('lastName')"
>
<span v-if="errors.lastName" class="text-red-500 text-[10px] mt-1 font-bold">{{ errors.lastName }}</span>
</div>
</div>
<div class="space-y-2">
<label class="text-xs font-black uppercase tracking-widest text-slate-400">เมล</label>
<input v-model="userData.email" type="email" class="premium-input w-full">
<label class="text-xs font-black uppercase tracking-widest text-slate-300">เมล</label>
<input
v-model="userData.email"
type="email"
class="premium-input w-full"
:class="{ '!border-red-500': errors.email }"
@input="clearFieldError('email')"
>
<span v-if="errors.email" class="text-red-500 text-[10px] mt-1 font-bold">{{ errors.email }}</span>
</div>
<div class="space-y-2">
<label class="text-xs font-black uppercase tracking-widest text-slate-400">เบอรโทรศพท</label>
<input v-model="userData.phone" type="text" class="premium-input w-full">
<label class="text-xs font-black uppercase tracking-widest text-slate-300">เบอรโทรศพท</label>
<input
v-model="userData.phone"
type="text"
class="premium-input w-full"
:class="{ '!border-red-500': errors.phone }"
@input="clearFieldError('phone')"
>
<span v-if="errors.phone" class="text-red-500 text-[10px] mt-1 font-bold">{{ errors.phone }}</span>
</div>
</div>
@ -189,16 +249,30 @@ const saveProfile = () => {
<h3 class="text-lg font-black text-white mb-6">ความปลอดภ</h3>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="space-y-2">
<label class="text-xs font-black uppercase tracking-widest text-slate-400">รหสผานปจจ</label>
<label class="text-xs font-black uppercase tracking-widest text-slate-300">รหสผานปจจ</label>
<input type="password" class="premium-input w-full" placeholder="••••••••">
</div>
<div class="space-y-2">
<label class="text-xs font-black uppercase tracking-widest text-slate-400">รหสผานใหม</label>
<input type="password" class="premium-input w-full">
<label class="text-xs font-black uppercase tracking-widest text-slate-300">รหสผานใหม</label>
<input
v-model="passwordForm.newPassword"
type="password"
class="premium-input w-full"
:class="{ '!border-red-500': errors.newPassword }"
@input="clearFieldError('newPassword')"
>
<span v-if="errors.newPassword" class="text-red-500 text-[10px] mt-1 font-bold">{{ errors.newPassword }}</span>
</div>
<div class="space-y-2">
<label class="text-xs font-black uppercase tracking-widest text-slate-400">นยนรหสผานใหม</label>
<input type="password" class="premium-input w-full">
<label class="text-xs font-black uppercase tracking-widest text-slate-300">นยนรหสผานใหม</label>
<input
v-model="passwordForm.confirmPassword"
type="password"
class="premium-input w-full"
:class="{ '!border-red-500': errors.confirmPassword }"
@input="clearFieldError('confirmPassword')"
>
<span v-if="errors.confirmPassword" class="text-red-500 text-[10px] mt-1 font-bold">{{ errors.confirmPassword }}</span>
</div>
</div>
</div>
@ -225,14 +299,14 @@ const saveProfile = () => {
}
.info-group .label {
@apply text-xs font-black uppercase tracking-widest text-slate-400 block mb-2;
@apply text-xs font-black uppercase tracking-widest text-slate-300 block mb-2;
}
.info-group .value {
@apply text-lg font-bold text-white;
}
.premium-input {
@apply bg-slate-100 dark:bg-slate-800/50 border border-slate-300 dark:border-white/5 rounded-2xl px-6 py-3.5 text-slate-900 dark:text-white focus:border-blue-500 outline-none transition-all;
@apply bg-slate-100 dark:bg-slate-900 border border-slate-300 dark:border-white/10 rounded-2xl px-6 py-3.5 text-slate-900 dark:text-white focus:border-blue-500 outline-none transition-all placeholder:text-slate-400;
}
.btn-premium-edit {
@ -240,7 +314,7 @@ const saveProfile = () => {
}
.btn-upload {
@apply px-6 py-2.5 bg-white dark:bg-white text-slate-900 dark:text-slate-900 rounded-xl text-xs font-black hover:bg-blue-50 transition-all;
@apply px-6 py-2.5 bg-blue-600 text-white rounded-xl text-xs font-black hover:bg-blue-500 transition-all shadow-lg shadow-blue-600/20;
}
.btn-save-premium {
@ -248,7 +322,7 @@ const saveProfile = () => {
}
.btn-cancel-premium {
@apply bg-slate-200 dark:bg-slate-800 text-slate-900 dark:text-slate-400 rounded-2xl py-4 font-black hover:bg-slate-300 dark:hover:bg-slate-700 dark:hover:text-white transition-all;
@apply bg-slate-200 dark:bg-slate-700 text-slate-900 dark:text-white rounded-2xl py-4 font-black hover:bg-slate-300 dark:hover:bg-slate-600 transition-all;
}
@media (max-width: 768px) {