feat: Implement initial e-learning platform frontend including landing page, course discovery, dashboard, and foundational UI components with i18n.

This commit is contained in:
supalerk-ar66 2026-02-26 15:20:44 +07:00
parent 5b9cf72046
commit 3a9da1007b
17 changed files with 1631 additions and 1524 deletions

View file

@ -5,6 +5,7 @@
* Features a transparent background that becomes solid/glass upon scrolling.
* Responsive: Collapses into a drawer on mobile (md breakpoint).
*/
const text = ref('');
// Track scrolling state to adjust header styling
const isScrolled = ref(false)
@ -41,24 +42,24 @@ onUnmounted(() => {
- Transitions between transparent and glass effect based on scroll.
-->
<header
class="fixed top-0 left-0 right-0 z-[100] transition-all duration-300"
:class="[isScrolled ? 'h-16 glass-nav shadow-lg' : 'h-24 bg-transparent']"
class="fixed top-0 left-0 right-0 z-[100] transition-all"
:class="[isScrolled ? 'h-20 glass-nav shadow-lg' : 'h-20 bg-transparent duration-300 border-b border-b-grey-7 ']"
>
<div class="container mx-auto px-6 md:px-12 h-full flex items-center justify-start">
<div class="container mx-auto px-6 md:px-12 h-full flex items-center justify-between">
<!-- Left Section: Logo -->
<NuxtLink to="/" class="flex items-center gap-3 group">
<div class="bg-blue-600 text-white font-black rounded-xl w-10 h-10 flex items-center justify-center shadow-lg shadow-blue-600/30 group-hover:scale-110 transition-transform">
E
<div class="bg-blue-600 text-white font-black rounded-full px-6 w-10 h-10 flex items-center justify-center group-hover:scale-110 transition-transform">
<q-icon name="o_school" size="24px" />
</div>
<div class="flex flex-col">
<span
class="font-black text-lg leading-none tracking-tight transition-colors"
class="font-bold text-lg leading-none tracking-tight transition-colors"
:class="[isScrolled ? 'text-white' : 'text-slate-900 group-hover:text-blue-600']"
>
E-Learning
EduLearn
</span>
<span
class="text-[10px] font-bold uppercase tracking-[0.2em] leading-none mt-1 transition-colors"
class="text-[10px] font-semibold uppercase tracking-[0.4em] leading-none mt-0.5 transition-colors"
:class="[isScrolled ? 'text-slate-400' : 'text-slate-500']"
>
Platform
@ -67,11 +68,11 @@ onUnmounted(() => {
</NuxtLink>
<!-- Desktop Navigation (Visible by default, hidden on mobile via CSS 'desktop-nav') -->
<nav class="flex desktop-nav items-center gap-8 text-sm font-bold ml-12">
<!-- <nav class="flex desktop-nav items-center gap-8 text-[16px] font-medium">
<NuxtLink
to="/browse"
class="transition-colors relative group py-2"
:class="[isScrolled ? 'text-slate-300 hover:text-white' : 'text-slate-600 hover:text-blue-600']"
:class="[isScrolled ? 'text-white hover:text-white' : 'text-grey-8 hover:text-blue-600']"
>
{{ $t('sidebar.onlineCourses') }}
<span class="absolute bottom-0 left-0 w-0 h-0.5 bg-blue-600 transition-all group-hover:w-full"/>
@ -79,21 +80,32 @@ onUnmounted(() => {
<NuxtLink
to="/browse/recommended"
class="transition-colors relative group py-2"
:class="[isScrolled ? 'text-slate-300 hover:text-white' : 'text-slate-600 hover:text-blue-600']"
:class="[isScrolled ? 'text-white hover:text-white' : 'text-grey-8 hover:text-blue-600']"
>
{{ $t('sidebar.recommendedCourses') }}
<span class="absolute bottom-0 left-0 w-0 h-0.5 bg-blue-600 transition-all group-hover:w-full"/>
</NuxtLink>
</nav>
</nav> -->
<!-- Desktop Action Buttons (Visible by default, hidden on mobile via CSS 'desktop-nav') -->
<div class="flex desktop-nav items-center gap-4 ml-auto">
<div class="flex desktop-nav items-center gap-4">
<q-input v-model="text" label="ค้นหาคอร์สเรียน..." rounded
standout="bg-black text-white"
:dark="isScrolled ? true : false"
>
<template v-slot:prepend>
<q-icon name="search" class="pl-3" color="grey-6"/>
</template>
</q-input>
<template v-if="!isAuthenticated">
<!-- Login Button -->
<NuxtLink
to="/auth/login"
class="px-6 py-2.5 rounded-xl font-bold text-sm border-2 transition-all hover:-translate-y-0.5"
:class="[isScrolled ? 'border-white/20 text-white hover:bg-white/10' : 'border-blue-100 text-blue-600 bg-blue-50 hover:bg-blue-100 hover:border-blue-200']"
class="px-5 py-4 rounded-full text-slate-700 font-semibold text-sm transition-all hover:-translate-y-0.5"
:class="[isScrolled ? 'border-white/20 text-white hover:bg-white/10' : 'border-white text-grey-9 bg-white hover:bg-blue-100 hover:border-blue-200']"
>
{{ $t('auth.login') }}
</NuxtLink>
@ -101,7 +113,7 @@ onUnmounted(() => {
<!-- Register Button -->
<NuxtLink
to="/auth/register"
class="px-6 py-2.5 rounded-xl font-bold text-sm text-white bg-gradient-to-br from-blue-600 to-indigo-600 shadow-lg shadow-blue-600/20 hover:shadow-blue-600/40 hover:-translate-y-0.5 transition-all"
class="px-5 py-4 rounded-full bg-blue-600 text-white font-semibold text-sm hover:shadow-blue-600/40 hover:-translate-y-0.5 transition-all"
>
{{ $t('auth.getStarted') }}
</NuxtLink>
@ -110,7 +122,7 @@ onUnmounted(() => {
<template v-else>
<NuxtLink
to="/dashboard"
class="px-6 py-2.5 rounded-xl font-bold text-sm text-white bg-gradient-to-br from-blue-600 to-indigo-600 shadow-lg shadow-blue-600/20 hover:shadow-blue-600/40 hover:-translate-y-0.5 transition-all"
class="bg-blue-600 text-white font-semibold text-sm px-5 py-4 rounded-full hover:shadow-blue-600/40 hover:-translate-y-0.5 transition-all"
>
{{ $t('landing.goToDashboard') }}
</NuxtLink>