@licklist/design 0.78.5-dev.35 → 0.78.5-dev.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/auth/Authorizer.d.ts.map +1 -1
  2. package/dist/auth/Authorizer.js +15 -11
  3. package/dist/index.js +1 -1
  4. package/dist/v2/components/NPSScore/NPSScore.d.ts +18 -0
  5. package/dist/v2/components/NPSScore/NPSScore.d.ts.map +1 -0
  6. package/dist/v2/components/NPSScore/index.d.ts +3 -0
  7. package/dist/v2/components/NPSScore/index.d.ts.map +1 -0
  8. package/dist/v2/components/UserPanel/UserPanel.js +168 -0
  9. package/dist/v2/components/UserPanel/UserPanel.scss.js +6 -0
  10. package/dist/v2/index.d.ts +4 -0
  11. package/dist/v2/index.d.ts.map +1 -1
  12. package/dist/v2/navigation/DashboardLayout/DashboardFooter.js +1 -1
  13. package/dist/v2/navigation/DashboardLayout/DashboardLayout.d.ts +8 -0
  14. package/dist/v2/navigation/DashboardLayout/DashboardLayout.d.ts.map +1 -1
  15. package/dist/v2/navigation/DashboardLayout/DashboardLayout.js +8 -2
  16. package/dist/v2/navigation/DashboardLayout/ProviderSidebar.d.ts +20 -0
  17. package/dist/v2/navigation/DashboardLayout/ProviderSidebar.d.ts.map +1 -1
  18. package/dist/v2/navigation/DashboardLayout/ProviderSidebar.js +66 -65
  19. package/dist/v2/navigation/DashboardLayout/TopNavigation.d.ts +5 -0
  20. package/dist/v2/navigation/DashboardLayout/TopNavigation.d.ts.map +1 -1
  21. package/dist/v2/navigation/DashboardLayout/TopNavigation.js +16 -1
  22. package/dist/v2/navigation/DashboardLayout/index.d.ts +1 -1
  23. package/dist/v2/navigation/DashboardLayout/index.d.ts.map +1 -1
  24. package/package.json +3 -3
  25. package/src/auth/Authorizer.tsx +23 -19
  26. package/src/v2/components/NPSScore/NPSScore.scss +330 -0
  27. package/src/v2/components/NPSScore/NPSScore.stories.tsx +29 -0
  28. package/src/v2/components/NPSScore/NPSScore.tsx +209 -0
  29. package/src/v2/components/NPSScore/index.ts +2 -0
  30. package/src/v2/dashboard-analytics/dashboard/Dashboard.stories.tsx +34 -0
  31. package/src/v2/index.ts +32 -0
  32. package/src/v2/navigation/DashboardLayout/DashboardFooter.tsx +1 -1
  33. package/src/v2/navigation/DashboardLayout/DashboardLayout.tsx +37 -12
  34. package/src/v2/navigation/DashboardLayout/ProviderSidebar.tsx +41 -23
  35. package/src/v2/navigation/DashboardLayout/TopNavigation.tsx +27 -1
  36. package/src/v2/navigation/DashboardLayout/index.ts +15 -1
@@ -0,0 +1,209 @@
1
+ import React, { useState } from 'react'
2
+ import './NPSScore.scss'
3
+
4
+ export interface NPSScoreProps {
5
+ /** User's first name for personalized greeting */
6
+ firstName?: string
7
+ /** Callback when NPS is submitted */
8
+ onSubmit?: (data: NPSSubmitData) => void
9
+ /** Callback when dismissed */
10
+ onDismiss?: () => void
11
+ }
12
+
13
+ export interface NPSSubmitData {
14
+ score: number
15
+ role: string
16
+ reason?: string
17
+ }
18
+
19
+ const roleOptions = [
20
+ { value: 'owner', label: 'Business Owner' },
21
+ { value: 'manager', label: 'Manager' },
22
+ { value: 'finance', label: 'Finance' },
23
+ { value: 'marketing', label: 'Marketing' },
24
+ { value: 'staff', label: 'Staff Member' },
25
+ { value: 'other', label: 'Other' },
26
+ ]
27
+
28
+ // Icons
29
+ const IconSad = ({ size = 24, className = '' }: { size?: number; className?: string }) => (
30
+ <svg width={size} height={size} viewBox="0 0 32 32" fill="none" className={className}>
31
+ <path d="M16 6C21.5228 6 26 10.4771 26 16C26 21.5228 21.5228 26 16 26C10.4771 26 6 21.5228 6 16C6 10.4771 10.4771 6 16 6ZM16 8C11.5817 8 8 11.5817 8 16C8 20.4183 11.5817 24 16 24C20.4183 24 24 20.4183 24 16C24 11.5817 20.4183 8 16 8ZM16 16C18.7614 16 21 18.2386 21 21H19C19 19.3431 17.6569 18 16 18C14.3431 18 13 19.3431 13 21H11C11 18.2386 13.2386 16 16 16ZM13.5 12C14.3284 12 15 12.6716 15 13.5C15 14.3284 14.3284 15 13.5 15C12.6716 15 12 14.3284 12 13.5C12 12.6716 12.6716 12 13.5 12ZM18.5 12C19.3284 12 20 12.6716 20 13.5C20 14.3284 19.3284 15 18.5 15C17.6716 15 17 14.3284 17 13.5C17 12.6716 17.6716 12 18.5 12Z" fill="currentColor" />
32
+ </svg>
33
+ )
34
+
35
+ const IconBigSmile = ({ size = 24, className = '' }: { size?: number; className?: string }) => (
36
+ <svg width={size} height={size} viewBox="0 0 32 32" fill="none" className={className}>
37
+ <path d="M16 6C21.5228 6 26 10.4771 26 16C26 21.5228 21.5228 26 16 26C10.4771 26 6 21.5228 6 16C6 10.4771 10.4771 6 16 6ZM16 8C11.5817 8 8 11.5817 8 16C8 20.4183 11.5817 24 16 24C20.4183 24 24 20.4183 24 16C24 11.5817 20.4183 8 16 8ZM21 17C21 19.7614 18.7614 22 16 22C13.2386 22 11 19.7614 11 17H21ZM13.5 11C14.3284 11 15 11.6716 15 12.5C15 13.3284 14.3284 14 13.5 14C12.6716 14 12 13.3284 12 12.5C12 11.6716 12.6716 11 13.5 11ZM18.5 11C19.3284 11 20 11.6716 20 12.5C20 13.3284 19.3284 14 18.5 14C17.6716 14 17 13.3284 17 12.5C17 11.6716 17.6716 11 18.5 11Z" fill="currentColor" />
38
+ </svg>
39
+ )
40
+
41
+ export const NPSScore: React.FC<NPSScoreProps> = ({
42
+ firstName,
43
+ onSubmit,
44
+ onDismiss,
45
+ }) => {
46
+ const [selectedScore, setSelectedScore] = useState<number | null>(null)
47
+ const [reason, setReason] = useState('')
48
+ const [role, setRole] = useState('')
49
+ const [isSubmitting, setIsSubmitting] = useState(false)
50
+ const [errors, setErrors] = useState<{ reason?: string; role?: string }>({})
51
+ const [showReasonField, setShowReasonField] = useState(false)
52
+ const [isSubmitted, setIsSubmitted] = useState(false)
53
+
54
+ const handleSubmit = async () => {
55
+ if (!selectedScore) return
56
+
57
+ // Validate required fields - reason required for all scores
58
+ const newErrors: { reason?: string; role?: string } = {}
59
+ if (!reason.trim()) {
60
+ newErrors.reason = 'Please provide a reason for your score'
61
+ }
62
+ if (!role) {
63
+ newErrors.role = 'Please select your role'
64
+ }
65
+
66
+ if (Object.keys(newErrors).length > 0) {
67
+ setErrors(newErrors)
68
+ return
69
+ }
70
+
71
+ setErrors({})
72
+ setIsSubmitting(true)
73
+
74
+ try {
75
+ await onSubmit?.({
76
+ score: selectedScore,
77
+ role,
78
+ reason: reason.trim() || undefined,
79
+ })
80
+ setIsSubmitted(true)
81
+ } finally {
82
+ setIsSubmitting(false)
83
+ }
84
+ }
85
+
86
+ if (isSubmitted) {
87
+ return (
88
+ <div className="nps-score">
89
+ <div className="nps-score__container">
90
+ <div className="nps-score__success">
91
+ <IconBigSmile size={48} className="nps-score__success-icon" />
92
+ <h3 className="nps-score__success-title">Thank you!</h3>
93
+ <p className="nps-score__success-message">Your feedback has been submitted successfully.</p>
94
+ </div>
95
+ </div>
96
+ </div>
97
+ )
98
+ }
99
+
100
+ return (
101
+ <div className="nps-score">
102
+ <div className="nps-score__container">
103
+ {/* Question */}
104
+ <h3 className="nps-score__question">
105
+ {firstName ? `Hey ${firstName}, how` : 'How'} likely would you be to recommend Booked it to a friend or colleague?
106
+ </h3>
107
+
108
+ {/* Scale labels */}
109
+ <div className="nps-score__labels">
110
+ <div className="nps-score__label">
111
+ <IconSad size={24} className="nps-score__label-icon" />
112
+ <span>Not Likely</span>
113
+ </div>
114
+ <div className="nps-score__label nps-score__label--desktop">
115
+ <span>Most Likely</span>
116
+ <IconBigSmile size={24} className="nps-score__label-icon" />
117
+ </div>
118
+ </div>
119
+
120
+ {/* Score buttons */}
121
+ <div className="nps-score__buttons">
122
+ {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((score) => (
123
+ <button
124
+ key={score}
125
+ onClick={() => setSelectedScore(score)}
126
+ className={`nps-score__button ${selectedScore === score ? 'nps-score__button--selected' : ''}`}
127
+ >
128
+ {score}
129
+ </button>
130
+ ))}
131
+ </div>
132
+
133
+ {/* Mobile label for Most Likely */}
134
+ <div className="nps-score__label nps-score__label--mobile">
135
+ <span>Most Likely</span>
136
+ <IconBigSmile size={24} className="nps-score__label-icon" />
137
+ </div>
138
+
139
+ {/* Expanded section after score selection */}
140
+ {selectedScore !== null && (
141
+ <div className="nps-score__expanded">
142
+ {/* Reason textarea - always visible */}
143
+ <div className="nps-score__field">
144
+ <label className="nps-score__field-label">
145
+ Reason for this score?
146
+ </label>
147
+ <textarea
148
+ value={reason}
149
+ onChange={(e) => {
150
+ setReason(e.target.value)
151
+ if (errors.reason) setErrors(prev => ({ ...prev, reason: undefined }))
152
+ }}
153
+ placeholder=""
154
+ className={`nps-score__textarea ${errors.reason ? 'nps-score__textarea--error' : ''}`}
155
+ />
156
+ {errors.reason ? (
157
+ <p className="nps-score__error">{errors.reason}</p>
158
+ ) : (
159
+ <p className="nps-score__hint">
160
+ Help us improve by explaining your score.
161
+ </p>
162
+ )}
163
+ </div>
164
+
165
+ {/* Role selection */}
166
+ <div className="nps-score__field nps-score__field--roles">
167
+ <label className="nps-score__field-label">
168
+ The role that best describes you?
169
+ </label>
170
+ <div className="nps-score__roles">
171
+ {roleOptions.map((option) => (
172
+ <label key={option.value} className="nps-score__role">
173
+ <input
174
+ type="radio"
175
+ name="role"
176
+ value={option.value}
177
+ checked={role === option.value}
178
+ onChange={(e) => {
179
+ setRole(e.target.value)
180
+ if (errors.role) setErrors(prev => ({ ...prev, role: undefined }))
181
+ }}
182
+ className="nps-score__role-input"
183
+ />
184
+ <span className="nps-score__role-radio"></span>
185
+ <span className="nps-score__role-label">{option.label}</span>
186
+ </label>
187
+ ))}
188
+ </div>
189
+ {errors.role && (
190
+ <p className="nps-score__error">{errors.role}</p>
191
+ )}
192
+ </div>
193
+
194
+ {/* Submit button */}
195
+ <button
196
+ onClick={handleSubmit}
197
+ disabled={isSubmitting}
198
+ className="nps-score__submit"
199
+ >
200
+ {isSubmitting ? 'Submitting...' : 'Submit'}
201
+ </button>
202
+ </div>
203
+ )}
204
+ </div>
205
+ </div>
206
+ )
207
+ }
208
+
209
+ export default NPSScore
@@ -0,0 +1,2 @@
1
+ export { NPSScore } from './NPSScore'
2
+ export type { NPSScoreProps, NPSSubmitData } from './NPSScore'
@@ -1,6 +1,7 @@
1
1
  import React, { useState } from 'react';
2
2
  import type { Meta, StoryObj } from '@storybook/react';
3
3
  import { Dashboard } from './Dashboard';
4
+ import { NPSScore } from '../../components/NPSScore';
4
5
 
5
6
  type TimeFilter = 'Today' | 'Yesterday' | 'This Week';
6
7
  type DatasetType = 'Bookings For' | 'Bookings Made';
@@ -261,4 +262,37 @@ export const ThisWeek = () => {
261
262
  }}
262
263
  />
263
264
  );
265
+ };
266
+
267
+ export const WithNPSScore = () => {
268
+ const [timeFilter, setTimeFilter] = useState<TimeFilter>('Today');
269
+
270
+ return (
271
+ <div style={{ padding: '24px' }}>
272
+ <NPSScore
273
+ firstName="Godwin"
274
+ onSubmit={(data) => {
275
+ console.log('NPS Submitted:', data);
276
+ return Promise.resolve();
277
+ }}
278
+ />
279
+ <Dashboard
280
+ timeFilter={timeFilter}
281
+ metrics={mockMetrics}
282
+ bookingsChart={{
283
+ title: 'Bookings',
284
+ subtitle: 'Today',
285
+ data: mockBookingsData,
286
+ isRevenue: false,
287
+ }}
288
+ revenueChart={{
289
+ title: 'Revenue',
290
+ subtitle: 'Today',
291
+ data: mockRevenueData,
292
+ isRevenue: true,
293
+ }}
294
+ onFilterChange={setTimeFilter}
295
+ />
296
+ </div>
297
+ );
264
298
  };
package/src/v2/index.ts CHANGED
@@ -28,6 +28,9 @@ export type { EntityHeaderProps } from './components/EntityHeader'
28
28
  // Tooltip Component
29
29
  export { Tooltip } from './components/Tooltip'
30
30
  export type { TooltipProps } from './components/Tooltip'
31
+ // NPSScore Component
32
+ export { NPSScore } from './components/NPSScore'
33
+ export type { NPSScoreProps, NPSSubmitData } from './components/NPSScore'
31
34
 
32
35
  // UserPanel Component
33
36
  export { UserPanel } from './components/UserPanel'
@@ -72,6 +75,35 @@ export type { SidebarUserElementProps } from './navigation/SidebarUserElement'
72
75
  export { SidebarWithAuth } from './navigation/SidebarWithAuth'
73
76
  export type { SidebarWithAuthProps } from './navigation/SidebarWithAuth'
74
77
 
78
+ // Dashboard Layout (Complete layout with sidebar, tophat, and content area)
79
+ export {
80
+ DashboardLayout,
81
+ ProviderSidebar,
82
+ AdminSidebar,
83
+ TopNavigation,
84
+ DashboardFooter,
85
+ // Sidebar Icons
86
+ HomeIcon,
87
+ FlowsIcon,
88
+ InventoryIcon,
89
+ LoyaltyIcon,
90
+ CustomersIcon,
91
+ ReportsIcon,
92
+ AnalyticsIcon,
93
+ MarketingIcon,
94
+ WaiversIcon,
95
+ SettingsIcon,
96
+ } from './navigation/DashboardLayout'
97
+ export type {
98
+ DashboardLayoutProps,
99
+ DestinationType,
100
+ ProviderSidebarProps,
101
+ NavItem,
102
+ AdminSidebarProps,
103
+ TopNavigationProps,
104
+ DashboardFooterProps
105
+ } from './navigation/DashboardLayout'
106
+
75
107
  // Navigation Configuration
76
108
  export { NAVIGATION_ITEMS } from './navigation/config'
77
109
 
@@ -6,7 +6,7 @@ export interface DashboardFooterProps {
6
6
  }
7
7
 
8
8
  export const DashboardFooter: React.FC<DashboardFooterProps> = ({
9
- version = '1.0.0'
9
+ version
10
10
  }) => {
11
11
  const currentYear = new Date().getFullYear()
12
12
 
@@ -1,6 +1,6 @@
1
1
  import React, { useState } from 'react'
2
2
  import { TopNavigation } from './TopNavigation'
3
- import { ProviderSidebar } from './ProviderSidebar'
3
+ import { ProviderSidebar, NavItem } from './ProviderSidebar'
4
4
  import { AdminSidebar } from './AdminSidebar'
5
5
  import { DashboardFooter } from './DashboardFooter'
6
6
  import './DashboardLayout.scss'
@@ -32,6 +32,12 @@ export interface DashboardLayoutProps {
32
32
  userInitials?: string
33
33
 
34
34
  userName?: string
35
+
36
+ userEmail?: string
37
+
38
+ userId?: number
39
+
40
+ userRole?: string
35
41
 
36
42
  inboxCount?: number
37
43
 
@@ -48,6 +54,10 @@ export interface DashboardLayoutProps {
48
54
  onBellClick?: () => void
49
55
 
50
56
  onHelpClick?: () => void
57
+
58
+ onProfileClick?: () => void
59
+
60
+ onLogoutClick?: () => void
51
61
 
52
62
  hasAdminAccess?: boolean
53
63
 
@@ -60,35 +70,44 @@ export interface DashboardLayoutProps {
60
70
  showFooter?: boolean
61
71
 
62
72
  userPanelOpen?: boolean
73
+
74
+ /** Custom navigation items for provider sidebar */
75
+ navItems?: NavItem[]
63
76
  }
64
77
 
65
78
  export const DashboardLayout: React.FC<DashboardLayoutProps> = ({
66
- destination = 'provider',
67
- sidebarExpanded = true,
79
+ destination,
80
+ sidebarExpanded,
68
81
  onSidebarToggle,
69
- providerName = "Sharky's Soft Play",
70
- providerId = "123",
82
+ providerName,
83
+ providerId,
71
84
  providerImage,
72
85
  providerType = 'venue',
73
- companyName = "Entertainment Group",
74
- companyId = "456",
86
+ companyName,
87
+ companyId,
75
88
  companyImage,
76
- userInitials = "GA",
77
- userName = "Godwin",
78
- inboxCount = 3,
79
- bellCount = 12,
89
+ userInitials,
90
+ userName,
91
+ userEmail,
92
+ userId,
93
+ userRole,
94
+ inboxCount = 0,
95
+ bellCount = 0,
80
96
  activePath = '/home',
81
97
  onNavigation,
82
98
  onUserClick,
83
99
  onInboxClick,
84
100
  onBellClick,
85
101
  onHelpClick,
102
+ onProfileClick,
103
+ onLogoutClick,
86
104
  hasAdminAccess = false,
87
105
  children,
88
106
  isMobile = false,
89
- version = '1.0.0',
107
+ version,
90
108
  showFooter = true,
91
109
  userPanelOpen = false,
110
+ navItems,
92
111
  }) => {
93
112
  const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
94
113
 
@@ -122,6 +141,7 @@ export const DashboardLayout: React.FC<DashboardLayoutProps> = ({
122
141
  onNavigation={onNavigation}
123
142
  showBackToAdmin={hasAdminAccess && destination !== 'admin'}
124
143
  onBackToAdmin={() => onNavigation?.('/admin')}
144
+ navItems={navItems}
125
145
  />
126
146
  )
127
147
  }
@@ -137,12 +157,17 @@ export const DashboardLayout: React.FC<DashboardLayoutProps> = ({
137
157
  onSidebarToggle={handleSidebarToggle}
138
158
  userInitials={userInitials}
139
159
  userName={userName}
160
+ userEmail={userEmail}
161
+ userId={userId}
162
+ userRole={userRole}
140
163
  inboxCount={inboxCount}
141
164
  notificationCount={bellCount}
142
165
  onUserClick={onUserClick}
143
166
  onInboxClick={onInboxClick}
144
167
  onNotificationClick={onBellClick}
145
168
  onHelpClick={onHelpClick}
169
+ onProfileClick={onProfileClick}
170
+ onLogoutClick={onLogoutClick}
146
171
  mobileMenuOpen={mobileMenuOpen}
147
172
  onMobileMenuToggle={() => setMobileMenuOpen(!mobileMenuOpen)}
148
173
  userPanelOpen={userPanelOpen}
@@ -3,6 +3,14 @@ import './ProviderSidebar.scss'
3
3
  import { EntityHeader } from '../../components/EntityHeader'
4
4
  import { Tooltip } from '../../components/Tooltip'
5
5
 
6
+ export interface NavItem {
7
+ id: string
8
+ label: string
9
+ path: string
10
+ icon: React.ReactNode
11
+ end?: boolean
12
+ }
13
+
6
14
  export interface ProviderSidebarProps {
7
15
  expanded?: boolean
8
16
  providerName?: string
@@ -13,14 +21,8 @@ export interface ProviderSidebarProps {
13
21
  activePath?: string
14
22
  showBackToAdmin?: boolean
15
23
  onBackToAdmin?: () => void
16
- }
17
-
18
- interface NavItem {
19
- id: string
20
- label: string
21
- path: string
22
- icon: React.ReactNode
23
- end?: boolean
24
+ /** Custom navigation items - if not provided, uses default items */
25
+ navItems?: NavItem[]
24
26
  }
25
27
 
26
28
 
@@ -96,30 +98,46 @@ const BackArrowIcon = () => (
96
98
  </svg>
97
99
  )
98
100
 
101
+ // Export icons for reuse
102
+ export {
103
+ HomeIcon,
104
+ FlowsIcon,
105
+ InventoryIcon,
106
+ LoyaltyIcon,
107
+ CustomersIcon,
108
+ ReportsIcon,
109
+ AnalyticsIcon,
110
+ MarketingIcon,
111
+ WaiversIcon,
112
+ SettingsIcon,
113
+ }
114
+
115
+ // Default navigation items
116
+ const defaultNavItems: NavItem[] = [
117
+ { id: 'home', label: 'Home', path: '/home', icon: <HomeIcon />, end: true },
118
+ { id: 'flows', label: 'Flows', path: '/flows', icon: <FlowsIcon /> },
119
+ { id: 'inventory', label: 'Inventory', path: '/inventory', icon: <InventoryIcon /> },
120
+ { id: 'loyalty', label: 'Loyalty', path: '/loyalty', icon: <LoyaltyIcon /> },
121
+ { id: 'customers', label: 'Customers', path: '/customers', icon: <CustomersIcon /> },
122
+ { id: 'reports', label: 'Reports', path: '/reports', icon: <ReportsIcon /> },
123
+ { id: 'analytics', label: 'Analytics', path: '/analytics', icon: <AnalyticsIcon /> },
124
+ { id: 'marketing', label: 'Marketing', path: '/marketing', icon: <MarketingIcon /> },
125
+ { id: 'waivers', label: 'Waivers', path: '/waivers', icon: <WaiversIcon /> },
126
+ { id: 'settings', label: 'Settings', path: '/settings', icon: <SettingsIcon /> },
127
+ ]
128
+
99
129
  export const ProviderSidebar: React.FC<ProviderSidebarProps> = ({
100
130
  expanded = true,
101
- providerName = "Sharky's Soft Play",
102
- providerId = '01',
131
+ providerName,
132
+ providerId,
103
133
  providerImage,
104
134
  providerType = 'venue',
105
135
  onNavigation,
106
136
  activePath = '/home',
107
137
  showBackToAdmin = false,
108
138
  onBackToAdmin,
139
+ navItems = defaultNavItems,
109
140
  }) => {
110
-
111
- const navItems: NavItem[] = [
112
- { id: 'home', label: 'Home', path: '/home', icon: <HomeIcon />, end: true },
113
- { id: 'flows', label: 'Flows', path: '/flows', icon: <FlowsIcon /> },
114
- { id: 'inventory', label: 'Inventory', path: '/inventory', icon: <InventoryIcon /> },
115
- { id: 'loyalty', label: 'Loyalty', path: '/loyalty', icon: <LoyaltyIcon /> },
116
- { id: 'customers', label: 'Customers', path: '/customers', icon: <CustomersIcon /> },
117
- { id: 'reports', label: 'Reports', path: '/reports', icon: <ReportsIcon /> },
118
- { id: 'analytics', label: 'Analytics', path: '/analytics', icon: <AnalyticsIcon /> },
119
- { id: 'marketing', label: 'Marketing', path: '/marketing', icon: <MarketingIcon /> },
120
- { id: 'waivers', label: 'Waivers', path: '/waivers', icon: <WaiversIcon /> },
121
- { id: 'settings', label: 'Settings', path: '/settings', icon: <SettingsIcon /> },
122
- ]
123
141
 
124
142
  const isActive = (item: NavItem) => {
125
143
  if (item.end) {
@@ -3,18 +3,25 @@ import './TopNavigation.scss'
3
3
  import BookedLogoMark from './assets/BookedLogo_Mark.png'
4
4
  import { UserAvatar } from '../../components/UserAvatar'
5
5
  import { Tooltip } from '../../components/Tooltip'
6
+ import { UserPanel } from '../../components/UserPanel'
7
+
6
8
  export interface TopNavigationProps {
7
9
  sidebarCollapsed?: boolean
8
10
  onSidebarToggle?: () => void
9
11
  userInitials?: string
10
12
  userName?: string
13
+ userEmail?: string
11
14
  userAvatarUrl?: string
15
+ userId?: number
16
+ userRole?: string
12
17
  inboxCount?: number
13
18
  notificationCount?: number
14
19
  onUserClick?: () => void
15
20
  onInboxClick?: () => void
16
21
  onNotificationClick?: () => void
17
22
  onHelpClick?: () => void
23
+ onProfileClick?: () => void
24
+ onLogoutClick?: () => void
18
25
  mobileMenuOpen?: boolean
19
26
  onMobileMenuToggle?: () => void
20
27
  sidebarToggleDisabled?: boolean
@@ -124,17 +131,22 @@ export const TopNavigation: React.FC<TopNavigationProps> = ({
124
131
  onSidebarToggle,
125
132
  userInitials = 'U',
126
133
  userName = 'User',
134
+ userEmail,
127
135
  userAvatarUrl,
136
+ userId,
137
+ userRole,
128
138
  inboxCount = 0,
129
139
  notificationCount = 0,
130
140
  onUserClick,
131
141
  onInboxClick,
132
142
  onNotificationClick,
133
143
  onHelpClick,
144
+ onProfileClick,
145
+ onLogoutClick,
134
146
  mobileMenuOpen = false,
135
147
  onMobileMenuToggle,
136
148
  sidebarToggleDisabled = false,
137
- userPanelOpen,
149
+ userPanelOpen = false,
138
150
  }) => {
139
151
  const [hoveredItem, setHoveredItem] = useState<string | null>(null)
140
152
  const [isNotificationActive, setIsNotificationActive] = useState(false)
@@ -239,6 +251,20 @@ export const TopNavigation: React.FC<TopNavigationProps> = ({
239
251
  </button>
240
252
  </Tooltip>
241
253
  </div>
254
+
255
+ {/* User Panel */}
256
+ <UserPanel
257
+ isOpen={userPanelOpen}
258
+ onClose={() => onUserClick?.()}
259
+ userName={userName}
260
+ email={userEmail}
261
+ initials={userInitials}
262
+ avatarUrl={userAvatarUrl}
263
+ userNumber={userId}
264
+ userRole={userRole}
265
+ onProfileClick={onProfileClick}
266
+ onLogoutClick={onLogoutClick}
267
+ />
242
268
  </header>
243
269
  )
244
270
  }
@@ -1,5 +1,19 @@
1
1
  export { DashboardLayout, type DashboardLayoutProps, type DestinationType } from './DashboardLayout'
2
- export { ProviderSidebar, type ProviderSidebarProps } from './ProviderSidebar'
2
+ export {
3
+ ProviderSidebar,
4
+ type ProviderSidebarProps,
5
+ type NavItem,
6
+ HomeIcon,
7
+ FlowsIcon,
8
+ InventoryIcon,
9
+ LoyaltyIcon,
10
+ CustomersIcon,
11
+ ReportsIcon,
12
+ AnalyticsIcon,
13
+ MarketingIcon,
14
+ WaiversIcon,
15
+ SettingsIcon,
16
+ } from './ProviderSidebar'
3
17
  export { AdminSidebar, type AdminSidebarProps } from './AdminSidebar'
4
18
  export { TopNavigation, type TopNavigationProps } from './TopNavigation'
5
19
  export { DashboardFooter, type DashboardFooterProps } from './DashboardFooter'