sanketgiri commited on
Commit
83e79d9
·
verified ·
1 Parent(s): d134fbf

import React, { useContext, useState } from 'react';

Browse files

import { Link, useNavigate } from 'react-router-dom';
import { UserContext } from '../context/User';
import {
Button,
Container,
Icon,
Menu,
Segment,
} from 'semantic-ui-react';
import {
API,
getLogo,
getSystemName,
isAdmin,
isMobile,
showSuccess,
} from '../helpers';
import '../index.css';

// Header Buttons
let headerButtons = [
{
name: 'Channel',
to: '/channel',
icon: 'sitemap',
admin: true,
},
{
name: 'Token',
to: '/token',
icon: 'key',
},
{
name: 'Redemption',
to: '/redemption',
icon: 'dollar sign',
admin: true,
},
{
name: 'Topup',
to: '/topup',
icon: 'cart',
},
{
name: 'Users',
to: '/user',
icon: 'user',
admin: true,
},
{
name: 'Dashboard',
to: '/dashboard',
icon: 'chart bar',
},
{
name: 'Logs',
to: '/log',
icon: 'book',
},
{
name: 'Settings',
to: '/setting',
icon: 'setting',
},
{
name: 'Docs',
external: 'https://doc.llmx.in',
icon: 'file alternate outline',
},
];

if (localStorage.getItem('chat_link')) {
headerButtons.splice(1, 0, {
name: 'Chat',
to: '/chat',
icon: 'comments',
});
}

const Header = () => {
const [userState, userDispatch] = useContext(UserContext);
const navigate = useNavigate();
const [showSidebar, setShowSidebar] = useState(false);
const systemName = getSystemName();
const logo = getLogo();

async function logout() {
setShowSidebar(false);
await API.get('/api/user/logout');
showSuccess('Logout successful!');
userDispatch({ type: 'logout' });
localStorage.removeItem('user');
navigate('/login');
}

const toggleSidebar = () => setShowSidebar(!showSidebar);
const goHome = () => (window.location.href = 'https://llmx.in');

const renderButtons = (isMobile) =>
headerButtons.map((button) => {
if (button.admin && !isAdmin()) return null;
if (button.external) {
return (
<Menu.Item
key={button.name}
onClick={() => window.open(button.external, '_blank')}
style={{
fontSize: '15px',
fontWeight: '400',
color: '#555',
cursor: 'pointer',
}}
>
<Icon name={button.icon} style={{ marginRight: '4px' }} />
{button.name}
</Menu.Item>
);
}

if (isMobile) {
return (
<Menu.Item
key={button.name}
onClick={() => {
navigate(button.to);
setShowSidebar(false);
}}
style={{ fontSize: '15px' }}
>
<Icon name={button.icon} style={{ marginRight: '4px' }} />
{button.name}
</Menu.Item>
);
}

return (
<Menu.Item
key={button.name}
as={Link}
to={button.to}
style={{
fontSize: '15px',
fontWeight: '400',
color: '#555',
}}
>
<Icon name={button.icon} style={{ marginRight: '4px' }} />
{button.name}
</Menu.Item>
);
});

if (isMobile()) {
return (
<>
<Menu
borderless
size='large'
style={
showSidebar
? {
borderBottom: 'none',
marginBottom: '0',
borderTop: 'none',
height: '51px',
}
: { borderTop: 'none', height: '52px' }
}
>
<Container
style={{
width: '100%',
maxWidth: isMobile() ? '100%' : '1200px',
padding: isMobile() ? '0 10px' : '0 20px',
}}
>
<Menu.Item onClick={goHome} style={{ cursor: 'pointer' }}>
<img src={logo} alt='logo' style={{ marginRight: '0.75em' }} />
<div style={{ fontSize: '20px' }}>
<b>{systemName}</b>
</div>
</Menu.Item>
<Menu.Menu position='right'>
<Menu.Item onClick={toggleSidebar}>
<Icon name={showSidebar ? 'close' : 'sidebar'} />
</Menu.Item>
</Menu.Menu>
</Container>
</Menu>
{showSidebar ? (
<Segment style={{ marginTop: 0, borderTop: '0' }}>
<Menu secondary vertical style={{ width: '100%', margin: 0 }}>
{renderButtons(true)}
<Menu.Item>
{userState.user ? (
<Button onClick={logout} style={{ color: '#666666' }}>
Logout
</Button>
) : (
<>
<Button
onClick={() => {
setShowSidebar(false);
navigate('/login');
}}
>
Login
</Button>
<Button
onClick={() => {
setShowSidebar(false);
navigate('/register');
}}
>
Register
</Button>
</>
)}
</Menu.Item>
</Menu>
</Segment>
) : null}
</>
);
}

return (
<>
<Menu
borderless
style={{
borderTop: 'none',
boxShadow: 'rgba(0, 0, 0, 0.04) 0px 2px 12px 0px',
border: 'none',
}}
>
<Container
style={{
width: '100%',
maxWidth: isMobile() ? '100%' : '1200px',
padding: isMobile() ? '0 10px' : '0 20px',
}}
>
<Menu.Item onClick={goHome} style={{ cursor: 'pointer' }}>
<img src={logo} alt='logo' style={{ marginRight: '0.75em' }} />
<div
style={{
fontSize: '18px',
fontWeight: '500',
color: '#333',
}}
>
{systemName}
</div>
</Menu.Item>
{renderButtons(false)}
<Menu.Menu position='right'>
{userState.user ? (
<Menu.Item
name='Logout'
onClick={logout}
style={{
fontSize: '15px',
fontWeight: '400',
color: '#666',
cursor: 'pointer',
}}
/>
) : (
<Menu.Item
name='Login'
as={Link}
to='/login'
className='btn btn-link'
style={{
fontSize: '15px',
fontWeight: '400',
color: '#666',
}}
/>
)}
</Menu.Menu>
</Container>
</Menu>
</>
);
};

export default Header;
inhence this ui and add some animtion backend same

Files changed (5) hide show
  1. components/footer.js +7 -4
  2. components/navbar.js +190 -38
  3. index.html +46 -4
  4. script.js +84 -1
  5. style.css +91 -1
components/footer.js CHANGED
@@ -26,7 +26,6 @@ class CustomFooter extends HTMLElement {
26
  gap: 1.5rem;
27
  flex-wrap: wrap;
28
  }
29
-
30
  .footer-link {
31
  color: #475569;
32
  text-decoration: none;
@@ -34,14 +33,18 @@ class CustomFooter extends HTMLElement {
34
  display: flex;
35
  align-items: center;
36
  gap: 0.5rem;
37
- transition: color 0.2s ease;
 
 
 
 
38
  }
39
 
40
  .footer-link:hover {
41
  color: #0ea5e9;
 
42
  }
43
-
44
- .copyright {
45
  color: #64748b;
46
  font-size: 0.875rem;
47
  }
 
26
  gap: 1.5rem;
27
  flex-wrap: wrap;
28
  }
 
29
  .footer-link {
30
  color: #475569;
31
  text-decoration: none;
 
33
  display: flex;
34
  align-items: center;
35
  gap: 0.5rem;
36
+ transition: all 0.3s ease;
37
+ padding: 0.5rem 0.75rem;
38
+ border-radius: 8px;
39
+ position: relative;
40
+ overflow: hidden;
41
  }
42
 
43
  .footer-link:hover {
44
  color: #0ea5e9;
45
+ background: rgba(125, 211, 252, 0.1);
46
  }
47
+ .copyright {
 
48
  color: #64748b;
49
  font-size: 0.875rem;
50
  }
components/navbar.js CHANGED
@@ -1,3 +1,4 @@
 
1
  class CustomNavbar extends HTMLElement {
2
  connectedCallback() {
3
  this.attachShadow({ mode: 'open' });
@@ -9,13 +10,13 @@ class CustomNavbar extends HTMLElement {
9
  height: 80px;
10
  width: 100%;
11
  overflow: hidden;
12
- z-index: 10;
13
  }
14
 
15
  nav {
16
- background: rgba(255, 255, 255, 0.9);
17
- backdrop-filter: blur(10px);
18
- box-shadow: 0 4px 30px rgba(0, 0, 0, 0.05);
19
  padding: 0 2rem;
20
  height: 80px;
21
  display: flex;
@@ -23,16 +24,26 @@ class CustomNavbar extends HTMLElement {
23
  align-items: center;
24
  position: relative;
25
  z-index: 2;
 
26
  }
27
 
28
  .logo-container {
29
  display: flex;
30
  align-items: center;
31
  gap: 0.75rem;
 
 
 
 
 
 
32
  }
33
 
34
  .logo {
35
- color: #0ea5e9;
 
 
 
36
  font-weight: 700;
37
  font-size: 1.5rem;
38
  letter-spacing: -0.5px;
@@ -41,6 +52,13 @@ class CustomNavbar extends HTMLElement {
41
  .logo-img {
42
  height: 2.5rem;
43
  width: auto;
 
 
 
 
 
 
 
44
  }
45
 
46
  .nav-links {
@@ -59,27 +77,32 @@ class CustomNavbar extends HTMLElement {
59
  display: flex;
60
  align-items: center;
61
  gap: 0.5rem;
62
- padding: 0.5rem 0;
 
63
  position: relative;
 
 
64
  }
65
 
66
  .nav-link:hover {
67
  color: #0ea5e9;
 
 
68
  }
69
 
70
- .nav-link::after {
71
  content: '';
72
  position: absolute;
73
- bottom: 0;
74
- left: 0;
75
- width: 0;
76
- height: 2px;
77
- background: linear-gradient(90deg, #7dd3fc 0%, #4ade80 100%);
78
- transition: width 0.3s ease;
79
  }
80
 
81
- .nav-link:hover::after {
82
- width: 100%;
83
  }
84
 
85
  .nav-actions {
@@ -93,26 +116,48 @@ class CustomNavbar extends HTMLElement {
93
  color: white;
94
  border: none;
95
  padding: 0.5rem 1.25rem;
96
- border-radius: 9999px;
97
  font-weight: 600;
98
  cursor: pointer;
99
- transition: all 0.2s ease;
 
 
100
  }
101
 
102
  .login-btn:hover {
103
- transform: translateY(-2px);
104
- box-shadow: 0 4px 15px rgba(125, 211, 252, 0.3);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  }
106
 
107
  .logout-btn {
108
  color: #64748b;
109
  font-weight: 500;
110
  cursor: pointer;
111
- transition: color 0.2s ease;
 
 
112
  }
113
 
114
  .logout-btn:hover {
115
  color: #ef4444;
 
 
116
  }
117
 
118
  .mobile-menu-btn {
@@ -121,23 +166,32 @@ class CustomNavbar extends HTMLElement {
121
  border: none;
122
  cursor: pointer;
123
  color: #334155;
 
 
 
 
 
 
 
124
  }
125
 
126
  .mobile-menu {
127
- display: none;
128
- position: absolute;
129
  top: 80px;
130
  left: 0;
131
  right: 0;
132
- background: white;
 
 
133
  padding: 1rem;
134
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
135
- border-radius: 0 0 1rem 1rem;
136
- z-index: 1;
 
137
  }
138
 
139
  .mobile-menu.open {
140
- display: block;
141
  }
142
 
143
  .mobile-nav-links {
@@ -153,16 +207,47 @@ class CustomNavbar extends HTMLElement {
153
  color: #334155;
154
  text-decoration: none;
155
  font-weight: 500;
156
- padding: 0.75rem 1rem;
157
- border-radius: 0.5rem;
158
  display: flex;
159
  align-items: center;
160
  gap: 0.75rem;
 
161
  }
162
 
163
  .mobile-nav-link:hover {
164
- background: #f1f5f9;
 
 
 
 
 
 
165
  color: #0ea5e9;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  }
167
 
168
  @media (max-width: 1024px) {
@@ -177,7 +262,7 @@ class CustomNavbar extends HTMLElement {
177
  </style>
178
 
179
  <nav>
180
- <div class="logo-container">
181
  <img src="http://static.photos/blue/200x200/42" alt="Logo" class="logo-img">
182
  <span class="logo">LightStream</span>
183
  </div>
@@ -206,7 +291,7 @@ class CustomNavbar extends HTMLElement {
206
  </div>
207
  </nav>
208
 
209
- <div id="mobile-menu" class="mobile-menu hidden">
210
  <ul class="mobile-nav-links">
211
  <li><a href="/channel" class="mobile-nav-link"><i data-feather="sitemap"></i> Channel</a></li>
212
  <li><a href="/token" class="mobile-nav-link"><i data-feather="key"></i> Token</a></li>
@@ -223,21 +308,88 @@ class CustomNavbar extends HTMLElement {
223
  <script>
224
  feather.replace();
225
 
 
 
 
 
 
 
 
 
 
 
226
  this.shadowRoot.getElementById('menu-button').addEventListener('click', () => {
227
  const menu = this.shadowRoot.getElementById('mobile-menu');
228
- menu.classList.toggle('hidden');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
 
 
 
 
230
  const icon = this.shadowRoot.querySelector('#menu-button i');
231
- if (menu.classList.contains('hidden')) {
232
  icon.setAttribute('data-feather', 'menu');
233
- } else {
234
- icon.setAttribute('data-feather', 'x');
235
  }
236
- feather.replace();
237
  });
238
  </script>
239
  `;
240
  }
241
  }
242
 
243
- customElements.define('custom-navbar', CustomNavbar);
 
1
+
2
  class CustomNavbar extends HTMLElement {
3
  connectedCallback() {
4
  this.attachShadow({ mode: 'open' });
 
10
  height: 80px;
11
  width: 100%;
12
  overflow: hidden;
13
+ z-index: 50;
14
  }
15
 
16
  nav {
17
+ background: rgba(255, 255, 255, 0.95);
18
+ backdrop-filter: blur(20px);
19
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
20
  padding: 0 2rem;
21
  height: 80px;
22
  display: flex;
 
24
  align-items: center;
25
  position: relative;
26
  z-index: 2;
27
+ border-bottom: 1px solid rgba(255, 255, 255, 0.2);
28
  }
29
 
30
  .logo-container {
31
  display: flex;
32
  align-items: center;
33
  gap: 0.75rem;
34
+ cursor: pointer;
35
+ transition: all 0.3s ease;
36
+ }
37
+
38
+ .logo-container:hover {
39
+ transform: scale(1.05);
40
  }
41
 
42
  .logo {
43
+ background: linear-gradient(90deg, #7dd3fc 0%, #4ade80 100%);
44
+ -webkit-background-clip: text;
45
+ -webkit-text-fill-color: transparent;
46
+ background-clip: text;
47
  font-weight: 700;
48
  font-size: 1.5rem;
49
  letter-spacing: -0.5px;
 
52
  .logo-img {
53
  height: 2.5rem;
54
  width: auto;
55
+ border-radius: 12px;
56
+ box-shadow: 0 4px 15px rgba(125, 211, 252, 0.3);
57
+ transition: all 0.3s ease;
58
+ }
59
+
60
+ .logo-img:hover {
61
+ transform: rotate(5deg) scale(1.1);
62
  }
63
 
64
  .nav-links {
 
77
  display: flex;
78
  align-items: center;
79
  gap: 0.5rem;
80
+ padding: 0.5rem 0.75rem;
81
+ border-radius: 8px;
82
  position: relative;
83
+ overflow: hidden;
84
+ transition: all 0.3s ease;
85
  }
86
 
87
  .nav-link:hover {
88
  color: #0ea5e9;
89
+ background: rgba(125, 211, 252, 0.1);
90
+ transform: translateY(-2px);
91
  }
92
 
93
+ .nav-link::before {
94
  content: '';
95
  position: absolute;
96
+ top: 0;
97
+ left: -100%;
98
+ width: 100%;
99
+ height: 100%;
100
+ background: linear-gradient(90deg, transparent, rgba(125, 211, 252, 0.2), transparent);
101
+ transition: left 0.5s ease;
102
  }
103
 
104
+ .nav-link:hover::before {
105
+ left: 100%;
106
  }
107
 
108
  .nav-actions {
 
116
  color: white;
117
  border: none;
118
  padding: 0.5rem 1.25rem;
119
+ border-radius: 12px;
120
  font-weight: 600;
121
  cursor: pointer;
122
+ transition: all 0.3s ease;
123
+ position: relative;
124
+ overflow: hidden;
125
  }
126
 
127
  .login-btn:hover {
128
+ transform: translateY(-3px);
129
+ box-shadow: 0 8px 25px rgba(125, 211, 252, 0.4);
130
+ }
131
+
132
+ .login-btn::after {
133
+ content: '';
134
+ position: absolute;
135
+ top: -50%;
136
+ left: -50%;
137
+ width: 200%;
138
+ height: 200%;
139
+ background: radial-gradient(circle, rgba(255,255,255,0.3) 0%, rgba(255,255,255,0) 50%);
140
+ transform: scale(0);
141
+ transition: transform 0.5s ease;
142
+ }
143
+
144
+ .login-btn:hover::after {
145
+ transform: scale(1);
146
  }
147
 
148
  .logout-btn {
149
  color: #64748b;
150
  font-weight: 500;
151
  cursor: pointer;
152
+ padding: 0.5rem 1rem;
153
+ border-radius: 8px;
154
+ transition: all 0.3s ease;
155
  }
156
 
157
  .logout-btn:hover {
158
  color: #ef4444;
159
+ background: rgba(239, 68, 68, 0.1);
160
+ transform: translateY(-2px);
161
  }
162
 
163
  .mobile-menu-btn {
 
166
  border: none;
167
  cursor: pointer;
168
  color: #334155;
169
+ padding: 0.5rem;
170
+ border-radius: 8px;
171
+ transition: all 0.3s ease;
172
+ }
173
+
174
+ .mobile-menu-btn:hover {
175
+ background: rgba(125, 211, 252, 0.1);
176
  }
177
 
178
  .mobile-menu {
179
+ position: fixed;
 
180
  top: 80px;
181
  left: 0;
182
  right: 0;
183
+ bottom: 0;
184
+ background: rgba(255, 255, 255, 0.98);
185
+ backdrop-filter: blur(20px);
186
  padding: 1rem;
187
+ z-index: 49;
188
+ transform: translateX(-100%);
189
+ transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
190
+ overflow-y: auto;
191
  }
192
 
193
  .mobile-menu.open {
194
+ transform: translateX(0);
195
  }
196
 
197
  .mobile-nav-links {
 
207
  color: #334155;
208
  text-decoration: none;
209
  font-weight: 500;
210
+ padding: 1rem;
211
+ border-radius: 12px;
212
  display: flex;
213
  align-items: center;
214
  gap: 0.75rem;
215
+ transition: all 0.3s ease;
216
  }
217
 
218
  .mobile-nav-link:hover {
219
+ background: linear-gradient(90deg, rgba(125, 211, 252, 0.1) 0%, rgba(74, 222, 128, 0.1) 100%);
220
+ color: #0ea5e9;
221
+ transform: translateX(10px);
222
+ }
223
+
224
+ .active {
225
+ background: linear-gradient(90deg, rgba(125, 211, 252, 0.15) 0%, rgba(74, 222, 128, 0.15) 100%);
226
  color: #0ea5e9;
227
+ font-weight: 600;
228
+ }
229
+
230
+ .pulse-indicator {
231
+ position: absolute;
232
+ top: 8px;
233
+ right: 8px;
234
+ width: 8px;
235
+ height: 8px;
236
+ background: #4ade80;
237
+ border-radius: 50%;
238
+ animation: pulse 2s infinite;
239
+ }
240
+
241
+ @keyframes pulse {
242
+ 0% {
243
+ box-shadow: 0 0 0 0 rgba(74, 222, 128, 0.7);
244
+ }
245
+ 70% {
246
+ box-shadow: 0 0 0 10px rgba(74, 222, 128, 0);
247
+ }
248
+ 100% {
249
+ box-shadow: 0 0 0 0 rgba(74, 222, 128, 0);
250
+ }
251
  }
252
 
253
  @media (max-width: 1024px) {
 
262
  </style>
263
 
264
  <nav>
265
+ <div class="logo-container" onclick="window.location.href='/'">
266
  <img src="http://static.photos/blue/200x200/42" alt="Logo" class="logo-img">
267
  <span class="logo">LightStream</span>
268
  </div>
 
291
  </div>
292
  </nav>
293
 
294
+ <div id="mobile-menu" class="mobile-menu">
295
  <ul class="mobile-nav-links">
296
  <li><a href="/channel" class="mobile-nav-link"><i data-feather="sitemap"></i> Channel</a></li>
297
  <li><a href="/token" class="mobile-nav-link"><i data-feather="key"></i> Token</a></li>
 
308
  <script>
309
  feather.replace();
310
 
311
+ // Add animation to logo on load
312
+ setTimeout(() => {
313
+ const logoImg = this.shadowRoot.querySelector('.logo-img');
314
+ const logoContainer = this.shadowRoot.querySelector('.logo-container');
315
+
316
+ logoContainer.style.opacity = '1';
317
+ logoContainer.style.transform = 'translateY(0)';
318
+ }, 100);
319
+
320
+ // Mobile menu functionality with smooth animations
321
  this.shadowRoot.getElementById('menu-button').addEventListener('click', () => {
322
  const menu = this.shadowRoot.getElementById('mobile-menu');
323
+ const isOpen = menu.classList.contains('open');
324
+
325
+ if (isOpen) {
326
+ menu.classList.remove('open');
327
+ menu.style.transform = 'translateX(-100%)';
328
+ const icon = this.shadowRoot.querySelector('#menu-button i');
329
+ icon.setAttribute('data-feather', 'menu');
330
+ feather.replace();
331
+ document.body.style.overflow = 'auto';
332
+ document.documentElement.style.overflow = 'auto';
333
+ document.body.style.height = 'auto';
334
+ document.documentElement.style.height = 'auto';
335
+ document.body.style.position = 'static';
336
+ document.documentElement.style.position = 'static';
337
+ } else {
338
+ menu.classList.add('open');
339
+ menu.style.transform = 'translateX(0)';
340
+ const icon = this.shadowRoot.querySelector('#menu-button i');
341
+ icon.setAttribute('data-feather', 'x');
342
+ feather.replace();
343
+ document.body.style.overflow = 'hidden';
344
+ document.documentElement.style.overflow = 'hidden';
345
+ document.body.style.height = '100vh';
346
+ document.documentElement.style.height = '100vh';
347
+ document.body.style.position = 'fixed';
348
+ document.documentElement.style.position = 'fixed';
349
+ }
350
+ });
351
+
352
+ // Add hover effects to nav links
353
+ const navLinks = this.shadowRoot.querySelectorAll('.nav-link');
354
+ navLinks.forEach(link => {
355
+ link.addEventListener('mouseenter', () => {
356
+ link.style.transform = 'translateY(-2px)';
357
+ link.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.1);
358
+ });
359
+
360
+ link.addEventListener('mouseleave', () => {
361
+ link.style.transform = 'translateY(0)';
362
+ link.style.boxShadow = 'none';
363
+ });
364
+ });
365
+
366
+ // Add active state based on current URL
367
+ const currentPath = window.location.pathname;
368
+ const allLinks = this.shadowRoot.querySelectorAll('.nav-link, .mobile-nav-link');
369
+
370
+ allLinks.forEach(link => {
371
+ if (link.getAttribute('href') === currentPath) {
372
+ link.classList.add('active');
373
+ }
374
+ });
375
+
376
+ // Add click outside to close mobile menu
377
+ document.addEventListener('click', (e) => {
378
+ const menu = this.shadowRoot.getElementById('mobile-menu');
379
+ const menuButton = this.shadowRoot.getElementById('menu-button');
380
 
381
+ if (menu && menuButton && !menu.contains(e.target) && !menuButton.contains(e.target)) {
382
+ menu.classList.remove('open');
383
+ menu.style.transform = 'translateX(-100%)';
384
  const icon = this.shadowRoot.querySelector('#menu-button i');
385
+ if (icon) {
386
  icon.setAttribute('data-feather', 'menu');
387
+ feather.replace();
 
388
  }
 
389
  });
390
  </script>
391
  `;
392
  }
393
  }
394
 
395
+ customElements.define('custom-navbar', CustomNavbar);
index.html CHANGED
@@ -12,13 +12,55 @@
12
  </head>
13
  <body class="bg-gradient-to-br from-blue-50 to-green-50 min-h-screen">
14
  <custom-navbar></custom-navbar>
15
-
16
  <main class="container mx-auto px-4 py-8">
17
  <!-- Content will be loaded here by React -->
18
- <div id="root" class="bg-white rounded-xl shadow-md p-6"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </main>
20
-
21
- <custom-footer></custom-footer>
22
 
23
  <script src="components/navbar.js"></script>
24
  <script src="components/footer.js"></script>
 
12
  </head>
13
  <body class="bg-gradient-to-br from-blue-50 to-green-50 min-h-screen">
14
  <custom-navbar></custom-navbar>
 
15
  <main class="container mx-auto px-4 py-8">
16
  <!-- Content will be loaded here by React -->
17
+ <div id="root" class="bg-white/80 backdrop-blur-sm rounded-2xl shadow-xl border border-white/20 p-8 slide-up">
18
+ <div class="text-center mb-8 fade-in">
19
+ <h1 class="text-4xl font-bold gradient-text mb-4">Welcome to LightStream</h1>
20
+ <p class="text-gray-600 text-lg">Your AI-powered dashboard for seamless management</p>
21
+ </div>
22
+
23
+ <!-- Feature Grid with Animations -->
24
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
25
+ <div class="bg-gradient-to-br from-blue-50 to-green-50 rounded-xl p-6 border border-blue-100 hover-lift fade-in" style="animation-delay: 0.1s">
26
+ <div class="text-blue-500 mb-3">
27
+ <i data-feather="sitemap" class="w-8 h-8"></i>
28
+ </div>
29
+ <h3 class="text-xl font-semibold text-gray-800 mb-2">Channel Management</h3>
30
+ <p class="text-gray-600">Efficiently manage your communication channels</p>
31
+ </div>
32
+
33
+ <div class="bg-gradient-to-br from-purple-50 to-pink-50 rounded-xl p-6 border border-purple-100 hover-lift fade-in" style="animation-delay: 0.2s">
34
+ <div class="text-purple-500 mb-3">
35
+ <i data-feather="key" class="w-8 h-8"></i>
36
+ </div>
37
+ <h3 class="text-xl font-semibold text-gray-800 mb-2">Token System</h3>
38
+ <p class="text-gray-600">Secure and scalable token management</p>
39
+ </div>
40
+
41
+ <div class="bg-gradient-to-br from-green-50 to-blue-50 rounded-xl p-6 border border-green-100 hover-lift fade-in" style="animation-delay: 0.3s">
42
+ <div class="text-green-500 mb-3">
43
+ <i data-feather="dollar-sign" class="w-8 h-8"></i>
44
+ </div>
45
+ <h3 class="text-xl font-semibold text-gray-800 mb-2">Redemption Center</h3>
46
+ <p class="text-gray-600">Streamline your redemption processes</p>
47
+ </div>
48
+ </div>
49
+
50
+ <!-- Quick Stats -->
51
+ <div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-8">
52
+ <div class="bg-white rounded-lg p-4 shadow-sm border border-gray-100 fade-in" style="animation-delay: 0.4s">
53
+ <div class="text-center">
54
+ <div class="text-2xl font-bold text-blue-600 mb-1">1,234</div>
55
+ <div class="text-sm text-gray-500">Active Users</div>
56
+ </div>
57
+
58
+ <div class="bg-white rounded-lg p-4 shadow-sm border border-gray-100 fade-in" style="animation-delay: 0.5s">Active Tokens</div>
59
+ <div class="text-sm text-gray-500">Total Revenue</div>
60
+ </div>
61
+ </div>
62
  </main>
63
+ <custom-footer></custom-footer>
 
64
 
65
  <script src="components/navbar.js"></script>
66
  <script src="components/footer.js"></script>
script.js CHANGED
@@ -1,3 +1,4 @@
 
1
  // Shared JavaScript across all pages
2
  console.log('LightStream Dashboard loaded');
3
 
@@ -20,4 +21,86 @@ document.addEventListener('click', (e) => {
20
  if (mobileMenu && !mobileMenu.contains(e.target) && !menuButton.contains(e.target)) {
21
  mobileMenu.classList.add('hidden');
22
  }
23
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
  // Shared JavaScript across all pages
3
  console.log('LightStream Dashboard loaded');
4
 
 
21
  if (mobileMenu && !mobileMenu.contains(e.target) && !menuButton.contains(e.target)) {
22
  mobileMenu.classList.add('hidden');
23
  }
24
+ });
25
+
26
+ // Add scroll animations
27
+ function handleScrollAnimations() {
28
+ const elements = document.querySelectorAll('.fade-in, .slide-up, .bounce-in');
29
+
30
+ elements.forEach(element => {
31
+ const elementTop = element.getBoundingClientRect().top;
32
+ const elementVisible = 150;
33
+
34
+ if (elementTop < window.innerHeight - elementVisible) {
35
+ element.style.opacity = '1';
36
+ element.style.transform = 'translateY(0)';
37
+ }
38
+ });
39
+ }
40
+
41
+ // Initialize animations on load and scroll
42
+ window.addEventListener('load', handleScrollAnimations);
43
+ window.addEventListener('scroll', handleScrollAnimations);
44
+
45
+ // Add typing animation effect
46
+ function typeWriter(element, text, speed = 50) {
47
+ let i = 0;
48
+ element.innerHTML = '';
49
+
50
+ function type() {
51
+ if (i < text.length) {
52
+ element.innerHTML += text.charAt(i);
53
+ i++;
54
+ setTimeout(type, speed);
55
+ }
56
+ }
57
+
58
+ type();
59
+ }
60
+
61
+ // Add ripple effect to buttons
62
+ function addRippleEffect() {
63
+ const buttons = document.querySelectorAll('.login-btn, .logout-btn');
64
+
65
+ buttons.forEach(button => {
66
+ button.addEventListener('click', function(e) {
67
+ const ripple = document.createElement('span');
68
+ const rect = button.getBoundingClientRect();
69
+ const size = Math.max(rect.width, rect.height);
70
+ const x = e.clientX - rect.left - size / 2;
71
+ const y = e.clientY - rect.top - size / 2;
72
+
73
+ ripple.style.width = ripple.style.height = size + 'px';
74
+ ripple.style.left = x + 'px';
75
+ ripple.style.top = y + 'px';
76
+ ripple.style.position = 'absolute';
77
+ ripple.style.borderRadius = '50%';
78
+ ripple.style.background = 'rgba(255, 255, 255, 0.6);
79
+ ripple.style.transform = 'scale(0)';
80
+ ripple.style.transition = 'transform 0.6s ease, opacity 0.6s ease';
81
+ ripple.style.opacity = '1';
82
+ ripple.style.transform = 'scale(4)';
83
+ ripple.style.opacity = '0';
84
+
85
+ button.style.position = 'relative';
86
+ button.style.overflow = 'hidden';
87
+
88
+ button.appendChild(ripple);
89
+
90
+ setTimeout(() => {
91
+ ripple.remove();
92
+ }, 600);
93
+ });
94
+ });
95
+ }
96
+
97
+ // Initialize effects when DOM is loaded
98
+ document.addEventListener('DOMContentLoaded', function() {
99
+ addRippleEffect();
100
+
101
+ // Add staggered animation delays to grid items
102
+ const gridItems = document.querySelectorAll('.grid > div');
103
+ gridItems.forEach((item, index) => {
104
+ item.style.animationDelay = (index * 0.1) + 's';
105
+ });
106
+ });
style.css CHANGED
@@ -1,8 +1,10 @@
 
1
  /* Shared styles across all pages */
2
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
3
 
4
  body {
5
  font-family: 'Inter', sans-serif;
 
6
  }
7
 
8
  /* Smooth transitions */
@@ -23,4 +25,92 @@ a, button {
23
  }
24
  ::-webkit-scrollbar-thumb:hover {
25
  background: #0ea5e9;
26
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
  /* Shared styles across all pages */
3
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
4
 
5
  body {
6
  font-family: 'Inter', sans-serif;
7
+ overflow-x: hidden;
8
  }
9
 
10
  /* Smooth transitions */
 
25
  }
26
  ::-webkit-scrollbar-thumb:hover {
27
  background: #0ea5e9;
28
+ }
29
+
30
+ /* Animation classes */
31
+ .fade-in {
32
+ animation: fadeIn 0.6s ease-in-out;
33
+ }
34
+
35
+ .slide-up {
36
+ animation: slideUp 0.8s ease-out;
37
+ }
38
+
39
+ .pulse-glow {
40
+ animation: pulseGlow 2s infinite;
41
+ }
42
+
43
+ .bounce-in {
44
+ animation: bounceIn 0.8s ease-out;
45
+ }
46
+
47
+ @keyframes fadeIn {
48
+ from {
49
+ opacity: 0;
50
+ transform: translateY(20px);
51
+ }
52
+ to {
53
+ opacity: 1;
54
+ transform: translateY(0);
55
+ }
56
+ }
57
+
58
+ @keyframes slideUp {
59
+ from {
60
+ opacity: 0;
61
+ transform: translateY(30px);
62
+ }
63
+ to {
64
+ opacity: 1;
65
+ transform: translateY(0);
66
+ }
67
+ }
68
+
69
+ @keyframes pulseGlow {
70
+ 0%, 100% {
71
+ box-shadow: 0 0 20px rgba(125, 211, 252, 0.3);
72
+ }
73
+ 50% {
74
+ box-shadow: 0 0 30px rgba(125, 211, 252, 0.6);
75
+ }
76
+ }
77
+
78
+ @keyframes bounceIn {
79
+ 0% {
80
+ opacity: 0;
81
+ transform: scale(0.3);
82
+ }
83
+ 50% {
84
+ opacity: 1;
85
+ transform: scale(1.05);
86
+ }
87
+ 100% {
88
+ opacity: 1;
89
+ transform: scale(1);
90
+ }
91
+ }
92
+
93
+ /* Hover effects */
94
+ .hover-lift {
95
+ transition: all 0.3s ease;
96
+ }
97
+
98
+ .hover-lift:hover {
99
+ transform: translateY(-5px);
100
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
101
+ }
102
+
103
+ /* Glass morphism effect */
104
+ .glass {
105
+ background: rgba(255, 255, 255, 0.1);
106
+ backdrop-filter: blur(10px);
107
+ border: 1px solid rgba(255, 255, 255, 0.2);
108
+ }
109
+
110
+ /* Gradient text */
111
+ .gradient-text {
112
+ background: linear-gradient(90deg, #7dd3fc 0%, #4ade80 100%);
113
+ -webkit-background-clip: text;
114
+ -webkit-text-fill-color: transparent;
115
+ background-clip: text;
116
+ }