171 lines
12 KiB
TypeScript
171 lines
12 KiB
TypeScript
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
|
import { CoursesComponent } from './courses.component';
|
|
import { WalletComponent } from './wallet.component';
|
|
import { DataService } from './data.service';
|
|
|
|
@Component({
|
|
selector: 'app-student-dashboard',
|
|
imports: [CoursesComponent, WalletComponent],
|
|
template: `
|
|
<div class="min-h-screen flex flex-col relative overflow-hidden">
|
|
<!-- Background Shapes -->
|
|
<div class="fixed top-0 left-0 w-full h-full overflow-hidden -z-10 pointer-events-none">
|
|
<div class="absolute top-[-10%] left-[-10%] w-[40%] h-[40%] bg-violet-400/20 rounded-full blur-[120px] mix-blend-multiply animate-blob"></div>
|
|
<div class="absolute top-[20%] right-[-10%] w-[35%] h-[35%] bg-indigo-400/20 rounded-full blur-[120px] mix-blend-multiply animate-blob animation-delay-2000"></div>
|
|
<div class="absolute bottom-[-10%] left-[20%] w-[40%] h-[40%] bg-fuchsia-400/20 rounded-full blur-[120px] mix-blend-multiply animate-blob animation-delay-4000"></div>
|
|
</div>
|
|
|
|
<!-- Header -->
|
|
<header class="fixed top-0 left-0 right-0 z-50 glass-panel border-b border-white/40 shadow-sm transition-all duration-300">
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-20 flex items-center justify-between">
|
|
<div class="flex items-center gap-4">
|
|
<!-- Mobile Menu -->
|
|
<button class="lg:hidden p-2 text-slate-500 hover:bg-slate-100/50 rounded-xl transition-colors">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8h16M4 16h16" />
|
|
</svg>
|
|
</button>
|
|
<div class="flex flex-col">
|
|
<span class="text-2xl font-black bg-gradient-to-r from-violet-600 via-fuchsia-600 to-indigo-600 bg-clip-text text-transparent tracking-tighter drop-shadow-sm">MaktApp</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex items-center gap-6">
|
|
<!-- Notification Bell -->
|
|
<button class="relative group p-2 rounded-full hover:bg-slate-100/50 transition-colors">
|
|
<span class="absolute top-2 right-2.5 w-2 h-2 bg-red-500 rounded-full ring-2 ring-white shadow-sm animate-pulse"></span>
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-slate-400 group-hover:text-indigo-600 transition-colors" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
|
|
</svg>
|
|
</button>
|
|
|
|
<!-- Avatar -->
|
|
<div class="flex items-center gap-3 pl-6 border-l border-slate-200/60 cursor-pointer group">
|
|
<div class="text-right hidden sm:block">
|
|
<p class="text-sm font-bold text-slate-800 group-hover:text-indigo-600 transition-colors">{{ user().displayName }}</p>
|
|
<p class="text-xs text-slate-500 font-medium">Student</p>
|
|
</div>
|
|
<div class="relative">
|
|
<div class="absolute inset-0 bg-gradient-to-tr from-violet-500 to-fuchsia-500 rounded-full blur-[2px] opacity-0 group-hover:opacity-100 transition-opacity"></div>
|
|
<img [src]="user().photoURL" alt="Profile" class="relative w-11 h-11 rounded-full ring-2 ring-white shadow-md object-cover">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Main Content -->
|
|
<main class="flex-grow w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 mt-24">
|
|
<!-- Hero Section -->
|
|
<div class="relative glass-card rounded-3xl p-8 mb-10 overflow-hidden shadow-xl shadow-indigo-100/50 ring-1 ring-white/60 animate-fade-in-up">
|
|
<!-- Decorative Gradients -->
|
|
<div class="absolute top-0 right-0 w-[600px] h-[600px] bg-gradient-to-br from-violet-100/60 to-fuchsia-100/40 rounded-full blur-3xl -mr-32 -mt-32 pointer-events-none"></div>
|
|
|
|
<div class="relative z-10 flex flex-col md:flex-row md:items-center justify-between gap-8">
|
|
<div class="max-w-2xl">
|
|
<h1 class="text-5xl font-extrabold text-slate-900 mb-4 tracking-tight leading-tight">
|
|
Welcome back, <br>
|
|
<span class="text-gradient-primary">{{ user().displayName }}!</span>
|
|
</h1>
|
|
<p class="text-slate-500 text-lg leading-relaxed mb-8 font-medium">
|
|
You're crushing your goals! You've completed <span class="font-bold text-slate-800">85%</span> of your weekly targets.
|
|
</p>
|
|
|
|
<div class="flex flex-wrap items-center gap-6">
|
|
<!-- Stat 1 -->
|
|
<div class="flex items-center gap-4 bg-white/70 backdrop-blur-md p-4 pr-8 rounded-2xl border border-white/60 shadow-sm hover:shadow-md transition-shadow">
|
|
<div class="w-14 h-14 rounded-2xl bg-gradient-to-br from-violet-500 to-indigo-600 text-white flex items-center justify-center shadow-lg shadow-indigo-500/30">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<p class="text-3xl font-bold text-slate-800 leading-none">{{ user().activeCoursesCount }}</p>
|
|
<p class="text-xs font-bold text-slate-400 uppercase tracking-wider mt-1">Active Courses</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Stat 2 -->
|
|
<div class="flex items-center gap-4 bg-white/70 backdrop-blur-md p-4 pr-8 rounded-2xl border border-white/60 shadow-sm hover:shadow-md transition-shadow">
|
|
<div class="w-14 h-14 rounded-2xl bg-gradient-to-br from-emerald-400 to-teal-500 text-white flex items-center justify-center shadow-lg shadow-emerald-500/30">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<p class="text-3xl font-bold text-slate-800 leading-none">{{ user().completionRate }}%</p>
|
|
<p class="text-xs font-bold text-slate-400 uppercase tracking-wider mt-1">Avg. Score</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<button class="relative group overflow-hidden bg-slate-900 text-white px-10 py-5 rounded-2xl font-bold shadow-2xl shadow-slate-900/30 transition-all hover:-translate-y-1 hover:shadow-slate-900/50 active:translate-y-0 active:scale-95 z-20">
|
|
<div class="absolute inset-0 bg-gradient-to-r from-violet-600 to-indigo-600 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
|
<span class="relative flex items-center gap-3 text-lg">
|
|
Resume Learning
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 transition-transform group-hover:translate-x-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
|
</svg>
|
|
</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8 items-start">
|
|
<!-- Courses Section (Left) -->
|
|
<div class="lg:col-span-2 w-full animate-fade-in-up delay-100">
|
|
<app-courses />
|
|
</div>
|
|
|
|
<!-- Wallet Section (Right) -->
|
|
<div class="lg:col-span-1 w-full sticky top-28 animate-fade-in-up delay-200">
|
|
<app-wallet />
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<!-- Mobile Bottom Nav -->
|
|
<nav class="md:hidden fixed bottom-6 left-6 right-6 glass-panel rounded-3xl shadow-2xl border border-white/60 flex justify-around p-4 z-50 ring-1 ring-black/5">
|
|
<button class="flex flex-col items-center gap-1 text-indigo-600 relative">
|
|
<div class="absolute -top-14 opacity-0 scale-50 transition-all duration-300 pointer-events-none">
|
|
<span class="px-3 py-1.5 bg-slate-800 text-white text-xs font-bold rounded-lg shadow-lg">Home</span>
|
|
</div>
|
|
<div class="p-2 bg-indigo-50 rounded-xl">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 drop-shadow-sm" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
|
|
</svg>
|
|
</div>
|
|
</button>
|
|
<button class="flex flex-col items-center gap-1 text-slate-400 hover:text-slate-600 transition-colors p-2">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
|
|
</svg>
|
|
</button>
|
|
<button class="flex flex-col items-center gap-1 text-slate-400 hover:text-slate-600 transition-colors p-2">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" />
|
|
</svg>
|
|
</button>
|
|
<button class="flex flex-col items-center gap-1 text-slate-400 hover:text-slate-600 transition-colors p-2">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
|
|
</svg>
|
|
</button>
|
|
</nav>
|
|
|
|
<!-- Footer -->
|
|
<footer class="mt-auto py-10 border-t border-slate-200/60 bg-white/40 backdrop-blur-md">
|
|
<div class="max-w-7xl mx-auto px-4 text-center">
|
|
<p class="text-sm font-semibold text-slate-400">© 2024 MaktApp. Crafted with ❤️ for students.</p>
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
`,
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
})
|
|
export class StudentDashboardComponent {
|
|
private dataService = inject(DataService);
|
|
user = this.dataService.currentUser;
|
|
}
|