larxius commited on
Commit
5187fdc
·
verified ·
1 Parent(s): 94c8343

Update frontend/src/components/Layout.jsx

Browse files
Files changed (1) hide show
  1. frontend/src/components/Layout.jsx +69 -17
frontend/src/components/Layout.jsx CHANGED
@@ -2,6 +2,40 @@ import React, { useState, useEffect, useRef } from 'react';
2
  import { Link, NavLink, useNavigate, useLocation } from 'react-router-dom';
3
  import { useAuth } from './AuthContext';
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  export const Layout = ({ children }) => {
6
  const { user, logout } = useAuth();
7
  const navigate = useNavigate();
@@ -199,17 +233,20 @@ export const Layout = ({ children }) => {
199
  {/* Header Branding */}
200
  <div className="mb-xl flex flex-col gap-sm">
201
  <div className="flex items-center gap-sm">
202
- <div className="h-14 flex items-center justify-center">
203
  <img src="/logo.png" alt="LarShield Logo" className="h-full object-contain" />
204
  </div>
205
- <div>
206
- <h1 className="font-bold brand-gradient tracking-tight m-0 text-[15px] leading-snug">LarShield</h1>
207
- <p className="font-label-sm text-[12px] text-on-surface-variant uppercase tracking-wider m-0 font-semibold">
208
- {user?.role === 'super_admin' ? 'Super Admin' :
209
- user?.role === 'admin' ? 'Admin' :
210
- user?.role === 'support_engineer' ? 'Support Engineer' :
211
- user?.role === 'org_admin' ? 'Organization Admin' :
212
- user?.subscription_tier || 'Free Tier'}
 
 
 
213
  </p>
214
  </div>
215
  </div>
@@ -282,7 +319,13 @@ export const Layout = ({ children }) => {
282
  {/* Mobile Hamburger menu */}
283
  <div className="md:hidden flex items-center gap-sm">
284
  <span className="material-symbols-outlined text-primary cursor-pointer">menu</span>
285
- <span className="font-bold brand-gradient text-[15px] leading-snug">LarShield</span>
 
 
 
 
 
 
286
  </div>
287
 
288
  {/* Search Bar Utility */}
@@ -448,7 +491,7 @@ export const Layout = ({ children }) => {
448
  <span className="material-symbols-outlined" style={{ fontSize: '18px' }}>calendar_today</span>
449
  </button>
450
  )}
451
-
452
  {user && (
453
  <div className="relative ml-sm" ref={profileRef}>
454
  <button
@@ -458,17 +501,26 @@ export const Layout = ({ children }) => {
458
  }}
459
  className="flex items-center gap-xs border-0 bg-transparent cursor-pointer hover:opacity-80 transition-opacity"
460
  >
461
- <span className="material-symbols-outlined text-on-surface-variant dark:text-surface-variant" style={{ fontSize: '28px', fontVariationSettings: "'FILL' 1" }}>account_circle</span>
 
 
462
  <span className="hidden lg:inline text-xs font-semibold text-on-surface-variant dark:text-surface-variant">
463
- {user.email.split('@')[0]}
464
  </span>
465
  </button>
466
 
467
  {isProfileOpen && (
468
- <div className="absolute right-0 mt-xs w-48 bg-surface border border-outline-variant rounded-lg shadow-lg overflow-hidden z-50">
469
- <div className="px-md py-sm border-b border-outline-variant bg-surface-container-low">
470
- <p className="font-label-md text-label-md font-bold text-on-surface truncate">{user.email}</p>
471
- <p className="font-body-sm text-body-sm text-on-surface-variant capitalize">{(user.role || 'User').replace(/_/g, ' ')}</p>
 
 
 
 
 
 
 
472
  </div>
473
  <div className="p-xs">
474
  <button
 
2
  import { Link, NavLink, useNavigate, useLocation } from 'react-router-dom';
3
  import { useAuth } from './AuthContext';
4
 
5
+ export const getInitials = (userData) => {
6
+ if (!userData) return 'DP';
7
+ const firstName = (userData.first_name || '').trim();
8
+ const lastName = (userData.last_name || '').trim();
9
+ if (firstName || lastName) {
10
+ const f = firstName.charAt(0);
11
+ const l = lastName.charAt(0);
12
+ if (f && l) return `${f}${l}`.toUpperCase();
13
+ if (f) return f.toUpperCase();
14
+ if (l) return l.toUpperCase();
15
+ }
16
+ const name = (userData.name || userData.full_name || '').trim();
17
+ if (name) {
18
+ const parts = name.split(/\s+/);
19
+ if (parts.length >= 2) {
20
+ return `${parts[0].charAt(0)}${parts[parts.length - 1].charAt(0)}`.toUpperCase();
21
+ }
22
+ return name.substring(0, 2).toUpperCase();
23
+ }
24
+ const email = (userData.email || '').trim();
25
+ if (email) {
26
+ const username = email.split('@')[0];
27
+ const parts = username.split(/[._-]/);
28
+ if (parts.length >= 2 && parts[0] && parts[1]) {
29
+ return `${parts[0].charAt(0)}${parts[1].charAt(0)}`.toUpperCase();
30
+ }
31
+ if (username.length >= 2) {
32
+ return username.substring(0, 2).toUpperCase();
33
+ }
34
+ return username.charAt(0).toUpperCase();
35
+ }
36
+ return 'DP';
37
+ };
38
+
39
  export const Layout = ({ children }) => {
40
  const { user, logout } = useAuth();
41
  const navigate = useNavigate();
 
233
  {/* Header Branding */}
234
  <div className="mb-xl flex flex-col gap-sm">
235
  <div className="flex items-center gap-sm">
236
+ <div className="h-12 flex items-center justify-center shrink-0">
237
  <img src="/logo.png" alt="LarShield Logo" className="h-full object-contain" />
238
  </div>
239
+ <div className="flex flex-col justify-center">
240
+ <h1 className="font-extrabold tracking-tight m-0 text-[18px] leading-none flex items-center">
241
+ <span className="text-[#0b132a] dark:text-white">Lar</span>
242
+ <span className="text-[#5856d6]">Shield</span>
243
+ </h1>
244
+ <p className="text-[12px] text-[#d97706] uppercase tracking-[0.16em] m-0 font-semibold leading-tight mt-1">
245
+ {user?.role === 'super_admin' ? 'SUPER ADMIN' :
246
+ user?.role === 'admin' ? 'ADMIN' :
247
+ user?.role === 'support_engineer' ? 'SUPPORT ENGINEER' :
248
+ user?.role === 'org_admin' ? 'ORGANIZATION ADMIN' :
249
+ (user?.subscription_tier ? `${user.subscription_tier.toUpperCase()} TIER` : 'FREE TIER')}
250
  </p>
251
  </div>
252
  </div>
 
319
  {/* Mobile Hamburger menu */}
320
  <div className="md:hidden flex items-center gap-sm">
321
  <span className="material-symbols-outlined text-primary cursor-pointer">menu</span>
322
+ <div className="flex items-center gap-xs">
323
+ <img src="/logo.png" alt="LarShield Logo" className="h-7 w-7 object-contain" />
324
+ <span className="font-extrabold tracking-tight text-[16px] leading-none flex items-center">
325
+ <span className="text-[#0b132a] dark:text-white">Lar</span>
326
+ <span className="text-[#5856d6]">Shield</span>
327
+ </span>
328
+ </div>
329
  </div>
330
 
331
  {/* Search Bar Utility */}
 
491
  <span className="material-symbols-outlined" style={{ fontSize: '18px' }}>calendar_today</span>
492
  </button>
493
  )}
494
+
495
  {user && (
496
  <div className="relative ml-sm" ref={profileRef}>
497
  <button
 
501
  }}
502
  className="flex items-center gap-xs border-0 bg-transparent cursor-pointer hover:opacity-80 transition-opacity"
503
  >
504
+ <div className="w-8 h-8 rounded-full bg-primary/10 text-primary border border-primary/20 flex items-center justify-center font-bold text-xs uppercase shadow-sm">
505
+ {getInitials(user)}
506
+ </div>
507
  <span className="hidden lg:inline text-xs font-semibold text-on-surface-variant dark:text-surface-variant">
508
+ {user.first_name || user.last_name ? `${user.first_name || ''} ${user.last_name || ''}`.trim() : user.email.split('@')[0]}
509
  </span>
510
  </button>
511
 
512
  {isProfileOpen && (
513
+ <div className="absolute right-0 mt-xs w-52 bg-surface border border-outline-variant rounded-lg shadow-lg overflow-hidden z-50">
514
+ <div className="px-md py-sm border-b border-outline-variant bg-surface-container-low flex items-center gap-sm">
515
+ <div className="w-9 h-9 rounded-full bg-primary/10 text-primary border border-primary/20 flex items-center justify-center font-bold text-sm uppercase shrink-0">
516
+ {getInitials(user)}
517
+ </div>
518
+ <div className="flex flex-col min-w-0">
519
+ <p className="font-label-md text-label-md font-bold text-on-surface truncate m-0">
520
+ {user.first_name || user.last_name ? `${user.first_name || ''} ${user.last_name || ''}`.trim() : user.email}
521
+ </p>
522
+ <p className="font-body-sm text-[11px] text-on-surface-variant capitalize m-0 truncate">{(user.role || 'User').replace(/_/g, ' ')}</p>
523
+ </div>
524
  </div>
525
  <div className="p-xs">
526
  <button