LordOdin721 commited on
Commit
fee3420
·
verified ·
1 Parent(s): 3f40d9d

This project delivers a production‑ready online learning admin platform with a premium 3D graduation‑cap brand system, dark/light theming, and fully responsive UX, backed by a hosted REST API wired to a MySQL database (host: sql207.infinityfree.com, user: if0_40314195, password: QClTpJOogkd, database: if0_40314195_learning_platform) for real‑time reads/writes across users, courses, enrollments, assignments, submissions, certificates, payments, and analytics; the dashboard surfaces KPIs (users, courses, enrollments, revenue), popularity and revenue trends, while management views provide search, sort, pagination, status/date filters, safe CRUD with confirmation modals, mobile‑first tables, non‑overlapping hamburger navigation, and a reliable SQL query tool with result export; accessibility is enforced via high‑contrast tokens, keyboard focus, ARIA labels, and overlay fixes (no persistent blur), performance is optimized with lazy loading and minified assets, and deployment ships with schema.sql, optional seed data, health checks, structured logging, and CORS, ensuring a polished, secure, and demo‑ready experience end to end.

Browse files
Files changed (6) hide show
  1. README.md +8 -5
  2. components/navbar.js +88 -0
  3. components/sidebar.js +126 -0
  4. index.html +181 -19
  5. script.js +71 -0
  6. style.css +63 -18
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Edusphere Admin Portal
3
- emoji: 🔥
4
- colorFrom: gray
5
- colorTo: pink
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: EduSphere Admin Portal 🎓
3
+ colorFrom: pink
4
+ colorTo: gray
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://huggingface.co/deepsite).
components/navbar.js ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomNavbar extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ .theme-toggle {
7
+ transition: all 0.3s ease;
8
+ }
9
+
10
+ .theme-toggle:hover {
11
+ transform: rotate(15deg);
12
+ }
13
+
14
+ .dropdown {
15
+ opacity: 0;
16
+ visibility: hidden;
17
+ transform: translateY(-10px);
18
+ transition: all 0.2s ease;
19
+ }
20
+
21
+ .dropdown.active {
22
+ opacity: 1;
23
+ visibility: visible;
24
+ transform: translateY(0);
25
+ }
26
+ </style>
27
+ <nav class="bg-white dark:bg-gray-800 shadow-sm">
28
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
29
+ <div class="flex justify-between h-16">
30
+ <div class="flex items-center">
31
+ <div class="flex-shrink-0 flex items-center">
32
+ <i data-feather="book-open" class="h-8 w-8 text-primary-500"></i>
33
+ <span class="ml-2 text-xl font-bold text-gray-800 dark:text-white">EduSphere</span>
34
+ </div>
35
+ </div>
36
+ <div class="flex items-center space-x-4">
37
+ <button class="theme-toggle p-1 rounded-full text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 focus:outline-none">
38
+ <i data-feather="sun" class="hidden dark:block"></i>
39
+ <i data-feather="moon" class="dark:hidden"></i>
40
+ </button>
41
+
42
+ <div class="relative ml-3">
43
+ <div class="flex items-center">
44
+ <button id="user-menu-button" class="flex items-center space-x-2 max-w-xs rounded-full focus:outline-none">
45
+ <img class="h-8 w-8 rounded-full" src="http://static.photos/people/200x200/5" alt="">
46
+ <span class="hidden md:block text-sm font-medium text-gray-700 dark:text-gray-200">Admin</span>
47
+ </button>
48
+ </div>
49
+
50
+ <div id="user-menu" class="dropdown origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg py-1 bg-white dark:bg-gray-700 ring-1 ring-black ring-opacity-5 focus:outline-none">
51
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600">Your Profile</a>
52
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600">Settings</a>
53
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600">Sign out</a>
54
+ </div>
55
+ </div>
56
+ </div>
57
+ </div>
58
+ </div>
59
+ </nav>
60
+ `;
61
+
62
+ // Add event listeners
63
+ const themeToggle = this.shadowRoot.querySelector('.theme-toggle');
64
+ const userMenuButton = this.shadowRoot.getElementById('user-menu-button');
65
+ const userMenu = this.shadowRoot.getElementById('user-menu');
66
+
67
+ themeToggle.addEventListener('click', () => {
68
+ document.documentElement.classList.toggle('dark');
69
+ localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light');
70
+ });
71
+
72
+ userMenuButton.addEventListener('click', () => {
73
+ userMenu.classList.toggle('active');
74
+ });
75
+
76
+ // Close dropdown when clicking outside
77
+ document.addEventListener('click', (e) => {
78
+ if (!this.shadowRoot.contains(e.target)) {
79
+ userMenu.classList.remove('active');
80
+ }
81
+ });
82
+
83
+ // Initialize feather icons
84
+ feather.replace();
85
+ }
86
+ }
87
+
88
+ customElements.define('custom-navbar', CustomNavbar);
components/sidebar.js ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomSidebar extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ .nav-item {
7
+ transition: all 0.2s ease;
8
+ }
9
+
10
+ .nav-item:hover:not(.active) {
11
+ background-color: rgba(99, 102, 241, 0.1);
12
+ }
13
+
14
+ .nav-item.active {
15
+ background-color: rgba(99, 102, 241, 0.2);
16
+ border-left: 3px solid var(--primary-500);
17
+ }
18
+
19
+ .submenu {
20
+ max-height: 0;
21
+ overflow: hidden;
22
+ transition: max-height 0.3s ease-out;
23
+ }
24
+
25
+ .submenu.open {
26
+ max-height: 500px;
27
+ }
28
+
29
+ .rotate-90 {
30
+ transform: rotate(90deg);
31
+ }
32
+ </style>
33
+ <div class="hidden md:flex md:flex-shrink-0">
34
+ <div class="flex flex-col w-64 border-r border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 h-screen fixed">
35
+ <div class="h-0 flex-1 flex flex-col pt-5 pb-4 overflow-y-auto">
36
+ <div class="flex-1 px-3 space-y-1">
37
+ <a href="#" class="nav-item active flex items-center px-2 py-3 text-sm font-medium rounded-md text-gray-900 dark:text-white">
38
+ <i data-feather="home" class="mr-3 h-5 w-5"></i>
39
+ Dashboard
40
+ </a>
41
+
42
+ <div class="space-y-1">
43
+ <button class="nav-item flex items-center w-full px-2 py-3 text-sm font-medium rounded-md text-gray-900 dark:text-white">
44
+ <i data-feather="users" class="mr-3 h-5 w-5"></i>
45
+ <span class="flex-1 text-left">Users</span>
46
+ <i data-feather="chevron-down" class="h-4 w-4"></i>
47
+ </button>
48
+ <div class="submenu pl-11">
49
+ <a href="#" class="flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white">
50
+ All Users
51
+ </a>
52
+ <a href="#" class="flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white">
53
+ Add New
54
+ </a>
55
+ </div>
56
+ </div>
57
+
58
+ <div class="space-y-1">
59
+ <button class="nav-item flex items-center w-full px-2 py-3 text-sm font-medium rounded-md text-gray-900 dark:text-white">
60
+ <i data-feather="book" class="mr-3 h-5 w-5"></i>
61
+ <span class="flex-1 text-left">Courses</span>
62
+ <i data-feather="chevron-down" class="h-4 w-4"></i>
63
+ </button>
64
+ <div class="submenu pl-11">
65
+ <a href="#" class="flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white">
66
+ All Courses
67
+ </a>
68
+ <a href="#" class="flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white">
69
+ Add New
70
+ </a>
71
+ <a href="#" class="flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white">
72
+ Categories
73
+ </a>
74
+ </div>
75
+ </div>
76
+
77
+ <a href="#" class="nav-item flex items-center px-2 py-3 text-sm font-medium rounded-md text-gray-900 dark:text-white">
78
+ <i data-feather="clipboard" class="mr-3 h-5 w-5"></i>
79
+ Enrollments
80
+ </a>
81
+
82
+ <a href="#" class="nav-item flex items-center px-2 py-3 text-sm font-medium rounded-md text-gray-900 dark:text-white">
83
+ <i data-feather="file-text" class="mr-3 h-5 w-5"></i>
84
+ Assignments
85
+ </a>
86
+
87
+ <a href="#" class="nav-item flex items-center px-2 py-3 text-sm font-medium rounded-md text-gray-900 dark:text-white">
88
+ <i data-feather="award" class="mr-3 h-5 w-5"></i>
89
+ Certificates
90
+ </a>
91
+
92
+ <a href="#" class="nav-item flex items-center px-2 py-3 text-sm font-medium rounded-md text-gray-900 dark:text-white">
93
+ <i data-feather="credit-card" class="mr-3 h-5 w-5"></i>
94
+ Payments
95
+ </a>
96
+
97
+ <a href="#" class="nav-item flex items-center px-2 py-3 text-sm font-medium rounded-md text-gray-900 dark:text-white">
98
+ <i data-feather="settings" class="mr-3 h-5 w-5"></i>
99
+ Settings
100
+ </a>
101
+ </div>
102
+ </div>
103
+ </div>
104
+ </div>
105
+ `;
106
+
107
+ // Add event listeners for submenus
108
+ const submenuButtons = this.shadowRoot.querySelectorAll('button.nav-item');
109
+ submenuButtons.forEach(button => {
110
+ if (button.nextElementSibling && button.nextElementSibling.classList.contains('submenu')) {
111
+ button.addEventListener('click', () => {
112
+ const icon = button.querySelector('i:last-child');
113
+ const submenu = button.nextElementSibling;
114
+
115
+ submenu.classList.toggle('open');
116
+ icon.classList.toggle('rotate-90');
117
+ });
118
+ }
119
+ });
120
+
121
+ // Initialize feather icons
122
+ feather.replace();
123
+ }
124
+ }
125
+
126
+ customElements.define('custom-sidebar', CustomSidebar);
index.html CHANGED
@@ -1,19 +1,181 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en" class="dark">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>EduSphere Admin Dashboard</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ <script>
12
+ tailwind.config = {
13
+ theme: {
14
+ extend: {
15
+ colors: {
16
+ primary: {
17
+ 500: '#6366f1',
18
+ },
19
+ secondary: {
20
+ 500: '#8b5cf6',
21
+ }
22
+ }
23
+ }
24
+ }
25
+ }
26
+ </script>
27
+ </head>
28
+ <body class="bg-gray-50 dark:bg-gray-900 min-h-screen">
29
+ <custom-navbar></custom-navbar>
30
+ <div class="flex">
31
+ <custom-sidebar></custom-sidebar>
32
+
33
+ <main class="flex-1 p-6">
34
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-6">
35
+ <!-- Stats Cards -->
36
+ <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
37
+ <div class="flex items-center justify-between">
38
+ <div>
39
+ <p class="text-gray-500 dark:text-gray-400">Total Students</p>
40
+ <h3 class="text-2xl font-bold text-gray-800 dark:text-white">1,248</h3>
41
+ </div>
42
+ <div class="p-3 rounded-full bg-primary-500/10 text-primary-500">
43
+ <i data-feather="users"></i>
44
+ </div>
45
+ </div>
46
+ <p class="text-green-500 text-sm mt-2">+12% from last month</p>
47
+ </div>
48
+
49
+ <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
50
+ <div class="flex items-center justify-between">
51
+ <div>
52
+ <p class="text-gray-500 dark:text-gray-400">Active Courses</p>
53
+ <h3 class="text-2xl font-bold text-gray-800 dark:text-white">36</h3>
54
+ </div>
55
+ <div class="p-3 rounded-full bg-secondary-500/10 text-secondary-500">
56
+ <i data-feather="book"></i>
57
+ </div>
58
+ </div>
59
+ <p class="text-green-500 text-sm mt-2">+2 new this month</p>
60
+ </div>
61
+
62
+ <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
63
+ <div class="flex items-center justify-between">
64
+ <div>
65
+ <p class="text-gray-500 dark:text-gray-400">Revenue</p>
66
+ <h3 class="text-2xl font-bold text-gray-800 dark:text-white">$24,780</h3>
67
+ </div>
68
+ <div class="p-3 rounded-full bg-green-500/10 text-green-500">
69
+ <i data-feather="dollar-sign"></i>
70
+ </div>
71
+ </div>
72
+ <p class="text-green-500 text-sm mt-2">+8% from last month</p>
73
+ </div>
74
+
75
+ <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
76
+ <div class="flex items-center justify-between">
77
+ <div>
78
+ <p class="text-gray-500 dark:text-gray-400">Certificates Issued</p>
79
+ <h3 class="text-2xl font-bold text-gray-800 dark:text-white">423</h3>
80
+ </div>
81
+ <div class="p-3 rounded-full bg-yellow-500/10 text-yellow-500">
82
+ <i data-feather="award"></i>
83
+ </div>
84
+ </div>
85
+ <p class="text-green-500 text-sm mt-2">+15% from last month</p>
86
+ </div>
87
+ </div>
88
+
89
+ <!-- Charts Section -->
90
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
91
+ <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
92
+ <div class="flex items-center justify-between mb-4">
93
+ <h2 class="text-lg font-semibold text-gray-800 dark:text-white">Enrollment Trends</h2>
94
+ <div class="flex space-x-2">
95
+ <button class="px-3 py-1 text-sm bg-gray-100 dark:bg-gray-700 rounded">Monthly</button>
96
+ <button class="px-3 py-1 text-sm text-gray-500 dark:text-gray-400">Yearly</button>
97
+ </div>
98
+ </div>
99
+ <div class="h-64">
100
+ <!-- Chart placeholder -->
101
+ <div class="flex items-center justify-center h-full bg-gray-100 dark:bg-gray-700 rounded">
102
+ <p class="text-gray-500">Chart will appear here</p>
103
+ </div>
104
+ </div>
105
+ </div>
106
+
107
+ <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
108
+ <div class="flex items-center justify-between mb-4">
109
+ <h2 class="text-lg font-semibold text-gray-800 dark:text-white">Course Popularity</h2>
110
+ <div class="flex space-x-2">
111
+ <button class="px-3 py-1 text-sm bg-gray-100 dark:bg-gray-700 rounded">By Enrollments</button>
112
+ <button class="px-3 py-1 text-sm text-gray-500 dark:text-gray-400">By Revenue</button>
113
+ </div>
114
+ </div>
115
+ <div class="h-64">
116
+ <!-- Chart placeholder -->
117
+ <div class="flex items-center justify-center h-full bg-gray-100 dark:bg-gray-700 rounded">
118
+ <p class="text-gray-500">Chart will appear here</p>
119
+ </div>
120
+ </div>
121
+ </div>
122
+ </div>
123
+
124
+ <!-- Recent Activity -->
125
+ <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
126
+ <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
127
+ <h2 class="text-lg font-semibold text-gray-800 dark:text-white">Recent Activity</h2>
128
+ </div>
129
+ <div class="divide-y divide-gray-200 dark:divide-gray-700">
130
+ <!-- Activity Item -->
131
+ <div class="p-4 hover:bg-gray-50 dark:hover:bg-gray-700">
132
+ <div class="flex items-center">
133
+ <div class="flex-shrink-0">
134
+ <img class="h-10 w-10 rounded-full" src="http://static.photos/people/200x200/1" alt="">
135
+ </div>
136
+ <div class="ml-4">
137
+ <p class="text-sm font-medium text-gray-900 dark:text-white">Sarah Johnson enrolled in <span class="text-primary-500">Advanced JavaScript</span></p>
138
+ <p class="text-sm text-gray-500 dark:text-gray-400">2 hours ago</p>
139
+ </div>
140
+ </div>
141
+ </div>
142
+
143
+ <!-- More activity items -->
144
+ <div class="p-4 hover:bg-gray-50 dark:hover:bg-gray-700">
145
+ <div class="flex items-center">
146
+ <div class="flex-shrink-0">
147
+ <i data-feather="award" class="h-10 w-10 p-2 rounded-full bg-yellow-500/10 text-yellow-500"></i>
148
+ </div>
149
+ <div class="ml-4">
150
+ <p class="text-sm font-medium text-gray-900 dark:text-white">Certificate issued to <span class="text-primary-500">Michael Chen</span></p>
151
+ <p class="text-sm text-gray-500 dark:text-gray-400">5 hours ago</p>
152
+ </div>
153
+ </div>
154
+ </div>
155
+
156
+ <div class="p-4 hover:bg-gray-50 dark:hover:bg-gray-700">
157
+ <div class="flex items-center">
158
+ <div class="flex-shrink-0">
159
+ <i data-feather="dollar-sign" class="h-10 w-10 p-2 rounded-full bg-green-500/10 text-green-500"></i>
160
+ </div>
161
+ <div class="ml-4">
162
+ <p class="text-sm font-medium text-gray-900 dark:text-white">Payment received from <span class="text-primary-500">Emma Rodriguez</span></p>
163
+ <p class="text-sm text-gray-500 dark:text-gray-400">1 day ago</p>
164
+ </div>
165
+ </div>
166
+ </div>
167
+ </div>
168
+ <div class="px-6 py-3 bg-gray-50 dark:bg-gray-700 text-center">
169
+ <a href="#" class="text-sm font-medium text-primary-500 hover:text-primary-700 dark:hover:text-primary-400">View all activity</a>
170
+ </div>
171
+ </div>
172
+ </main>
173
+ </div>
174
+
175
+ <script src="components/navbar.js"></script>
176
+ <script src="components/sidebar.js"></script>
177
+ <script src="script.js"></script>
178
+ <script>feather.replace();</script>
179
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
180
+ </body>
181
+ </html>
script.js ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ document.addEventListener('DOMContentLoaded', () => {
2
+ // Check for saved theme preference
3
+ const savedTheme = localStorage.getItem('theme') || 'dark';
4
+ if (savedTheme === 'dark') {
5
+ document.documentElement.classList.add('dark');
6
+ } else {
7
+ document.documentElement.classList.remove('dark');
8
+ }
9
+
10
+ // Initialize tooltips
11
+ const initTooltips = () => {
12
+ const tooltipElements = document.querySelectorAll('[data-tooltip]');
13
+
14
+ tooltipElements.forEach(el => {
15
+ const tooltipId = 'tooltip-' + Math.random().toString(36).substr(2, 9);
16
+ const tooltipText = el.getAttribute('data-tooltip');
17
+
18
+ el.setAttribute('aria-describedby', tooltipId);
19
+
20
+ const tooltip = document.createElement('div');
21
+ tooltip.id = tooltipId;
22
+ tooltip.className = 'absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white bg-gray-900 rounded-lg shadow-sm tooltip dark:bg-gray-700';
23
+ tooltip.innerHTML = tooltipText;
24
+
25
+ document.body.appendChild(tooltip);
26
+
27
+ const popperInstance = Popper.createPopper(el, tooltip, {
28
+ placement: 'top',
29
+ modifiers: [
30
+ {
31
+ name: 'offset',
32
+ options: {
33
+ offset: [0, 8],
34
+ },
35
+ },
36
+ ],
37
+ });
38
+
39
+ const showEvents = ['mouseenter', 'focus'];
40
+ const hideEvents = ['mouseleave', 'blur'];
41
+
42
+ showEvents.forEach(event => {
43
+ el.addEventListener(event, () => {
44
+ tooltip.setAttribute('data-show', '');
45
+ popperInstance.update();
46
+ });
47
+ });
48
+
49
+ hideEvents.forEach(event => {
50
+ el.addEventListener(event, () => {
51
+ tooltip.removeAttribute('data-show');
52
+ });
53
+ });
54
+ });
55
+ };
56
+
57
+ // Check if Popper is loaded before initializing tooltips
58
+ const checkPopper = setInterval(() => {
59
+ if (typeof Popper !== 'undefined') {
60
+ clearInterval(checkPopper);
61
+ initTooltips();
62
+ }
63
+ }, 100);
64
+
65
+ // Add animations to dashboard cards
66
+ const dashboardCards = document.querySelectorAll('.bg-white, .dark\\:bg-gray-800');
67
+ dashboardCards.forEach((card, index) => {
68
+ card.style.animationDelay = `${index * 0.1}s`;
69
+ card.classList.add('slide-up');
70
+ });
71
+ });
style.css CHANGED
@@ -1,28 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
  body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
 
 
 
 
 
 
 
 
 
 
 
4
  }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
9
  }
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
  }
25
 
26
- .card p:last-child {
27
- margin-bottom: 0;
28
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
2
+
3
+ :root {
4
+ --primary-500: #6366f1;
5
+ --secondary-500: #8b5cf6;
6
+ }
7
+
8
+ * {
9
+ font-family: 'Inter', sans-serif;
10
+ transition: background-color 0.2s ease, color 0.2s ease;
11
+ }
12
+
13
  body {
14
+ -webkit-font-smoothing: antialiased;
15
+ -moz-osx-font-smoothing: grayscale;
16
+ }
17
+
18
+ /* Custom scrollbar */
19
+ ::-webkit-scrollbar {
20
+ width: 8px;
21
+ height: 8px;
22
+ }
23
+
24
+ ::-webkit-scrollbar-track {
25
+ background: #f1f1f1;
26
+ border-radius: 10px;
27
  }
28
 
29
+ .dark ::-webkit-scrollbar-track {
30
+ background: #374151;
 
31
  }
32
 
33
+ ::-webkit-scrollbar-thumb {
34
+ background: #c7d2fe;
35
+ border-radius: 10px;
 
 
36
  }
37
 
38
+ .dark ::-webkit-scrollbar-thumb {
39
+ background: #4f46e5;
 
 
 
 
40
  }
41
 
42
+ ::-webkit-scrollbar-thumb:hover {
43
+ background: #a5b4fc;
44
  }
45
+
46
+ .dark ::-webkit-scrollbar-thumb:hover {
47
+ background: #4338ca;
48
+ }
49
+
50
+ /* Animation classes */
51
+ .fade-in {
52
+ animation: fadeIn 0.3s ease-in-out;
53
+ }
54
+
55
+ @keyframes fadeIn {
56
+ from { opacity: 0; }
57
+ to { opacity: 1; }
58
+ }
59
+
60
+ .slide-up {
61
+ animation: slideUp 0.3s ease-out;
62
+ }
63
+
64
+ @keyframes slideUp {
65
+ from {
66
+ opacity: 0;
67
+ transform: translateY(10px);
68
+ }
69
+ to {
70
+ opacity: 1;
71
+ transform: translateY(0);
72
+ }
73
+ }