@licklist/design 0.78.27 → 0.78.29

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 (139) hide show
  1. package/dist/assets/Trend-Down.svg.js +16 -0
  2. package/dist/assets/Trend-Up.svg.js +16 -0
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +11 -0
  6. package/dist/v2/components/Button/Button.d.ts +8 -4
  7. package/dist/v2/components/Button/Button.d.ts.map +1 -1
  8. package/dist/v2/components/Button/index.d.ts +2 -2
  9. package/dist/v2/components/Button/index.d.ts.map +1 -1
  10. package/dist/v2/components/Checkbox/Checkbox.d.ts +9 -0
  11. package/dist/v2/components/Checkbox/Checkbox.d.ts.map +1 -0
  12. package/dist/v2/components/Checkbox/index.d.ts +3 -0
  13. package/dist/v2/components/Checkbox/index.d.ts.map +1 -0
  14. package/dist/v2/components/FormField/FormField.d.ts +10 -0
  15. package/dist/v2/components/FormField/FormField.d.ts.map +1 -0
  16. package/dist/v2/components/FormField/index.d.ts +3 -0
  17. package/dist/v2/components/FormField/index.d.ts.map +1 -0
  18. package/dist/v2/components/NewInput/NewInput.d.ts +20 -0
  19. package/dist/v2/components/NewInput/NewInput.d.ts.map +1 -0
  20. package/dist/v2/components/NewInput/index.d.ts +2 -0
  21. package/dist/v2/components/NewInput/index.d.ts.map +1 -0
  22. package/dist/v2/components/NewPageHeader/NewPageHeader.d.ts +10 -0
  23. package/dist/v2/components/NewPageHeader/NewPageHeader.d.ts.map +1 -0
  24. package/dist/v2/components/NewPageHeader/index.d.ts +2 -0
  25. package/dist/v2/components/NewPageHeader/index.d.ts.map +1 -0
  26. package/dist/v2/components/SectionHeader/SectionHeader.d.ts +8 -0
  27. package/dist/v2/components/SectionHeader/SectionHeader.d.ts.map +1 -0
  28. package/dist/v2/components/SectionHeader/index.d.ts +3 -0
  29. package/dist/v2/components/SectionHeader/index.d.ts.map +1 -0
  30. package/dist/v2/components/Select/Select.js +128 -0
  31. package/dist/v2/components/Select/Select.scss.js +6 -0
  32. package/dist/v2/components/WYSIWYGEditor/Icons.d.ts +16 -0
  33. package/dist/v2/components/WYSIWYGEditor/Icons.d.ts.map +1 -0
  34. package/dist/v2/components/WYSIWYGEditor/WYSIWYGEditor.d.ts +14 -0
  35. package/dist/v2/components/WYSIWYGEditor/WYSIWYGEditor.d.ts.map +1 -0
  36. package/dist/v2/components/WYSIWYGEditor/index.d.ts +3 -0
  37. package/dist/v2/components/WYSIWYGEditor/index.d.ts.map +1 -0
  38. package/dist/v2/components/index.d.ts +22 -0
  39. package/dist/v2/components/index.d.ts.map +1 -0
  40. package/dist/v2/dashboard-analytics/blog-posts/Blog.js +103 -0
  41. package/dist/v2/dashboard-analytics/blog-posts/Blog.scss.js +6 -0
  42. package/dist/v2/dashboard-analytics/chart/Chart.js +733 -0
  43. package/dist/v2/dashboard-analytics/chart/Chart.scss.js +6 -0
  44. package/dist/v2/dashboard-analytics/dashboard/Dashboard.js +270 -0
  45. package/dist/v2/dashboard-analytics/dashboard/Dashboard.scss.js +6 -0
  46. package/dist/v2/dashboard-analytics/metric-card/MetricCard.js +65 -0
  47. package/dist/v2/dashboard-analytics/metric-card/MetricCard.scss.js +6 -0
  48. package/dist/v2/dashboard-analytics/venue-card/VenueCard.js +50 -0
  49. package/dist/v2/dashboard-analytics/venue-card/VenueCard.scss.js +6 -0
  50. package/dist/v2/dashboard-analytics/venue-closed-card/VenueClosedCard.js +48 -0
  51. package/dist/v2/dashboard-analytics/venue-closed-card/VenueClosedCard.scss.js +6 -0
  52. package/dist/v2/{navigation/icons → icons}/index.d.ts +6 -0
  53. package/dist/v2/icons/index.d.ts.map +1 -0
  54. package/dist/v2/icons/index.js +113 -0
  55. package/dist/v2/index.d.ts +3 -1
  56. package/dist/v2/index.d.ts.map +1 -1
  57. package/dist/v2/navigation/DashboardLayout/TopNavigation.scss.js +1 -1
  58. package/dist/v2/navigation/DashboardLayout/index.d.ts +1 -0
  59. package/dist/v2/navigation/DashboardLayout/index.d.ts.map +1 -1
  60. package/dist/v2/navigation/index.d.ts +1 -1
  61. package/dist/v2/navigation/index.d.ts.map +1 -1
  62. package/dist/v2/pages/Settings/SettingsPage.d.ts +13 -0
  63. package/dist/v2/pages/Settings/SettingsPage.d.ts.map +1 -0
  64. package/dist/v2/pages/Settings/SettingsPage.js +88 -0
  65. package/dist/v2/pages/Settings/SettingsPage.scss.js +6 -0
  66. package/dist/v2/pages/Settings/SettingsTabs.d.ts +14 -0
  67. package/dist/v2/pages/Settings/SettingsTabs.d.ts.map +1 -0
  68. package/dist/v2/pages/Settings/SettingsTabs.js +29 -0
  69. package/dist/v2/pages/Settings/SettingsTabs.scss.js +6 -0
  70. package/dist/v2/pages/Settings/components/SidebarCustomisation.d.ts +20 -0
  71. package/dist/v2/pages/Settings/components/SidebarCustomisation.d.ts.map +1 -0
  72. package/dist/v2/pages/Settings/components/SidebarCustomisation.js +283 -0
  73. package/dist/v2/pages/Settings/components/SidebarCustomisation.scss.js +6 -0
  74. package/dist/v2/pages/Settings/components/SidebarNavItem.d.ts +19 -0
  75. package/dist/v2/pages/Settings/components/SidebarNavItem.d.ts.map +1 -0
  76. package/dist/v2/pages/Settings/components/SidebarNavItem.js +41 -0
  77. package/dist/v2/pages/Settings/components/SidebarNavItem.scss.js +6 -0
  78. package/dist/v2/pages/Settings/components/index.d.ts +5 -0
  79. package/dist/v2/pages/Settings/components/index.d.ts.map +1 -0
  80. package/dist/v2/pages/Settings/index.d.ts +7 -0
  81. package/dist/v2/pages/Settings/index.d.ts.map +1 -0
  82. package/package.json +3 -3
  83. package/src/index.ts +3 -1
  84. package/src/v2/components/Alert/Alert.scss +3 -3
  85. package/src/v2/components/Button/Button.tsx +34 -12
  86. package/src/v2/components/Button/index.ts +2 -2
  87. package/src/v2/components/Checkbox/Checkbox.scss +211 -0
  88. package/src/v2/components/Checkbox/Checkbox.stories.tsx +316 -0
  89. package/src/v2/components/Checkbox/Checkbox.tsx +106 -0
  90. package/src/v2/components/Checkbox/index.ts +3 -0
  91. package/src/v2/components/FormField/FormField.scss +87 -0
  92. package/src/v2/components/FormField/FormField.stories.tsx +71 -0
  93. package/src/v2/components/FormField/FormField.tsx +37 -0
  94. package/src/v2/components/FormField/index.ts +3 -0
  95. package/src/v2/components/NewInput/NewInput.stories.tsx +433 -0
  96. package/src/v2/components/NewInput/NewInput.tsx +96 -0
  97. package/src/v2/components/NewInput/index.ts +1 -0
  98. package/src/v2/components/NewPageHeader/NewPageHeader.scss +47 -0
  99. package/src/v2/components/NewPageHeader/NewPageHeader.stories.tsx +44 -0
  100. package/src/v2/components/NewPageHeader/NewPageHeader.tsx +35 -0
  101. package/src/v2/components/NewPageHeader/index.ts +1 -0
  102. package/src/v2/components/SectionHeader/SectionHeader.scss +11 -0
  103. package/src/v2/components/SectionHeader/SectionHeader.tsx +15 -0
  104. package/src/v2/components/SectionHeader/index.ts +2 -0
  105. package/src/v2/components/Select/Select.scss +5 -5
  106. package/src/v2/components/WYSIWYGEditor/Icons.tsx +93 -0
  107. package/src/v2/components/WYSIWYGEditor/WYSIWYGEditor.scss +310 -0
  108. package/src/v2/components/WYSIWYGEditor/WYSIWYGEditor.stories.tsx +252 -0
  109. package/src/v2/components/WYSIWYGEditor/WYSIWYGEditor.tsx +393 -0
  110. package/src/v2/components/WYSIWYGEditor/index.ts +3 -0
  111. package/src/v2/components/index.ts +37 -0
  112. package/src/v2/icons/index.tsx +105 -0
  113. package/src/v2/index.ts +10 -2
  114. package/src/v2/navigation/DashboardLayout/TopNavigation.scss +1 -0
  115. package/src/v2/navigation/DashboardLayout/index.ts +3 -0
  116. package/src/v2/navigation/Navigation/Navigation.tsx +1 -1
  117. package/src/v2/navigation/NavigationItem/NavigationItem.stories.tsx +1 -1
  118. package/src/v2/navigation/index.ts +1 -1
  119. package/src/v2/pages/Settings/SettingsContentPlaceholder.scss +24 -0
  120. package/src/v2/pages/Settings/SettingsPage.scss +52 -0
  121. package/src/v2/pages/Settings/SettingsPage.tsx +46 -0
  122. package/src/v2/pages/Settings/SettingsTabs.scss +44 -0
  123. package/src/v2/pages/Settings/SettingsTabs.tsx +36 -0
  124. package/src/v2/pages/Settings/components/SidebarCustomisation.scss +204 -0
  125. package/src/v2/pages/Settings/components/SidebarCustomisation.stories.tsx +48 -0
  126. package/src/v2/pages/Settings/components/SidebarCustomisation.tsx +172 -0
  127. package/src/v2/pages/Settings/components/SidebarNavItem.scss +76 -0
  128. package/src/v2/pages/Settings/components/SidebarNavItem.stories.tsx +50 -0
  129. package/src/v2/pages/Settings/components/SidebarNavItem.tsx +52 -0
  130. package/src/v2/pages/Settings/components/index.ts +5 -0
  131. package/src/v2/pages/Settings/index.ts +8 -0
  132. package/src/v2/styles/components/Button.scss +51 -53
  133. package/src/v2/styles/form/Layout.scss +15 -0
  134. package/src/v2/styles/form/NewInput.scss +83 -53
  135. package/src/v2/styles/index.scss +1 -0
  136. package/src/v2/styles/tokens/_colors.scss +6 -6
  137. package/src/v2/styles/tokens/_typography.scss +2 -2
  138. package/dist/v2/navigation/icons/index.d.ts.map +0 -1
  139. package/src/v2/navigation/icons/index.tsx +0 -72
@@ -0,0 +1,52 @@
1
+ @import '../../styles/tokens/typography';
2
+ @import '../../styles/tokens/colors';
3
+
4
+ .settings-page {
5
+ display: flex;
6
+ flex-direction: column;
7
+ align-items: flex-start;
8
+ gap: 24px;
9
+ align-self: stretch;
10
+ font-family: var(--font-family-sans);
11
+
12
+ &__header {
13
+ display: flex;
14
+ flex-direction: column;
15
+ align-items: flex-start;
16
+ align-self: stretch;
17
+ border-bottom: 1px solid var(--border-primary);
18
+ }
19
+
20
+ &__title-row {
21
+ display: flex;
22
+ height: 72px;
23
+ justify-content: space-between;
24
+ align-items: center;
25
+ align-self: stretch;
26
+ padding: 24px 0 8px 8px;
27
+
28
+ @media (max-width: $bp-mobile-max) {
29
+ height: auto;
30
+ padding: 16px 0 8px 8px;
31
+ }
32
+ }
33
+
34
+ &__title {
35
+ @include typography('heading.h1');
36
+ margin: 0;
37
+
38
+ @media (max-width: $bp-mobile-max) {
39
+ @include typography('heading.h1.mobile');
40
+ }
41
+ }
42
+
43
+ &__content {
44
+ display: flex;
45
+ flex-direction: column;
46
+ align-items: stretch;
47
+ gap: 16px;
48
+ align-self: stretch;
49
+ width: 100%;
50
+ padding: 0 8px;
51
+ }
52
+ }
@@ -0,0 +1,46 @@
1
+ import React, { useState } from 'react'
2
+ import './SettingsPage.scss'
3
+ import { SettingsTabs, SettingsTab } from './SettingsTabs'
4
+
5
+ export interface SettingsPageProps {
6
+ title?: string
7
+ tabs: SettingsTab[]
8
+ defaultTab?: string
9
+ onTabChange?: (tabId: string) => void
10
+ children?: React.ReactNode
11
+ }
12
+
13
+ export const SettingsPage: React.FC<SettingsPageProps> = ({
14
+ title = 'Settings',
15
+ tabs,
16
+ defaultTab,
17
+ onTabChange,
18
+ children,
19
+ }) => {
20
+ const [activeTab, setActiveTab] = useState(defaultTab || tabs[0]?.id || '')
21
+
22
+ const handleTabChange = (tabId: string) => {
23
+ setActiveTab(tabId)
24
+ onTabChange?.(tabId)
25
+ }
26
+
27
+ return (
28
+ <div className="settings-page">
29
+ <header className="settings-page__header">
30
+ <div className="settings-page__title-row">
31
+ <h1 className="settings-page__title">{title}</h1>
32
+ </div>
33
+ <SettingsTabs
34
+ tabs={tabs}
35
+ activeTab={activeTab}
36
+ onTabChange={handleTabChange}
37
+ />
38
+ </header>
39
+ <div className="settings-page__content">
40
+ {children}
41
+ </div>
42
+ </div>
43
+ )
44
+ }
45
+
46
+ export default SettingsPage
@@ -0,0 +1,44 @@
1
+ @import '../../styles/tokens/typography';
2
+ @import '../../styles/tokens/colors';
3
+
4
+ .settings-tabs {
5
+ display: flex;
6
+ align-items: flex-start;
7
+ gap: 24px;
8
+ align-self: stretch;
9
+ font-family: var(--font-family-sans);
10
+
11
+ &__tab {
12
+ display: flex;
13
+ padding: 12px 0;
14
+ justify-content: center;
15
+ align-items: center;
16
+ gap: 8px;
17
+ background: none;
18
+ border: none;
19
+ border-bottom: 2px solid transparent;
20
+ cursor: pointer;
21
+ transition: border-color 0.2s ease, color 0.2s ease;
22
+
23
+ &:hover {
24
+ .settings-tabs__tab-label {
25
+ color: var(--label-primary);
26
+ }
27
+ }
28
+
29
+ &--active {
30
+ border-bottom-color: var(--fill-primary);
31
+
32
+ .settings-tabs__tab-label {
33
+ color: var(--label-primary);
34
+ font-weight: 600;
35
+ }
36
+ }
37
+ }
38
+
39
+ &__tab-label {
40
+ @include typography('text.regular');
41
+ color: var(--label-secondary);
42
+ transition: color 0.2s ease;
43
+ }
44
+ }
@@ -0,0 +1,36 @@
1
+ import React from 'react'
2
+ import './SettingsTabs.scss'
3
+
4
+ export interface SettingsTab {
5
+ id: string
6
+ label: string
7
+ }
8
+
9
+ export interface SettingsTabsProps {
10
+ tabs: SettingsTab[]
11
+ activeTab: string
12
+ onTabChange: (tabId: string) => void
13
+ }
14
+
15
+ export const SettingsTabs: React.FC<SettingsTabsProps> = ({
16
+ tabs,
17
+ activeTab,
18
+ onTabChange,
19
+ }) => {
20
+ return (
21
+ <nav className="settings-tabs">
22
+ {tabs.map((tab) => (
23
+ <button
24
+ key={tab.id}
25
+ onClick={() => onTabChange(tab.id)}
26
+ className={`settings-tabs__tab ${activeTab === tab.id ? 'settings-tabs__tab--active' : ''}`}
27
+ >
28
+ <span className="settings-tabs__label">{tab.label}</span>
29
+ <div className="settings-tabs__indicator" />
30
+ </button>
31
+ ))}
32
+ </nav>
33
+ )
34
+ }
35
+
36
+ export default SettingsTabs
@@ -0,0 +1,204 @@
1
+ @import '../../../styles/tokens/typography';
2
+ @import '../../../styles/tokens/colors';
3
+
4
+ .sidebar-customisation {
5
+ display: flex;
6
+ flex-direction: column;
7
+ gap: 16px;
8
+ width: 100%;
9
+ font-family: var(--font-family-sans);
10
+
11
+ &__header {
12
+ display: flex;
13
+ justify-content: space-between;
14
+ align-items: center;
15
+ }
16
+
17
+ &__title {
18
+ font-size: 1rem;
19
+ font-weight: 600;
20
+ line-height: 1.2;
21
+ color: var(--label-primary);
22
+ margin: 0;
23
+ }
24
+
25
+ &__cancel-btn {
26
+ display: inline-flex;
27
+ align-items: center;
28
+ justify-content: center;
29
+ height: 36px;
30
+ padding: 0 12px;
31
+ border-radius: 6px;
32
+ border: none;
33
+ background: transparent;
34
+ color: var(--label-danger);
35
+ font-size: 14px;
36
+ font-weight: 500;
37
+ white-space: nowrap;
38
+ cursor: pointer;
39
+ transition: background-color 0.2s ease;
40
+
41
+ &:hover {
42
+ background-color: var(--surface-danger-soft, rgba(239, 68, 68, 0.1));
43
+ }
44
+
45
+ &:focus-visible {
46
+ outline: 2px solid var(--border-action);
47
+ outline-offset: 2px;
48
+ }
49
+ }
50
+
51
+ &__edit-btn {
52
+ display: inline-flex;
53
+ align-items: center;
54
+ justify-content: center;
55
+ gap: 6px;
56
+ height: 36px;
57
+ padding: 0 12px 0 4px;
58
+ border-radius: 6px;
59
+ border: none;
60
+ background: transparent;
61
+ color: var(--label-primary);
62
+ font-size: 14px;
63
+ font-weight: 500;
64
+ white-space: nowrap;
65
+ cursor: pointer;
66
+ transition: background-color 0.2s ease;
67
+
68
+ svg {
69
+ width: 20px;
70
+ height: 20px;
71
+ flex-shrink: 0;
72
+ fill: var(--fill-primary);
73
+ }
74
+
75
+ &:hover {
76
+ background-color: var(--surface-tertiary);
77
+ }
78
+
79
+ &:focus-visible {
80
+ outline: 2px solid var(--border-action);
81
+ outline-offset: 2px;
82
+ }
83
+ }
84
+
85
+ // Edit mode grid - responsive columns
86
+ &__grid {
87
+ display: grid;
88
+ grid-template-columns: 1fr;
89
+ gap: 16px;
90
+ width: 100%;
91
+
92
+ @media (min-width: 768px) {
93
+ grid-template-columns: repeat(2, 1fr);
94
+ }
95
+
96
+ @media (min-width: 1024px) {
97
+ grid-template-columns: repeat(3, 1fr);
98
+ }
99
+
100
+ @media (min-width: 1536px) {
101
+ grid-template-columns: repeat(4, 1fr);
102
+ }
103
+ }
104
+
105
+ // View mode grid - responsive columns
106
+ &__view-grid {
107
+ display: grid;
108
+ grid-template-columns: 1fr;
109
+ gap: 12px;
110
+ width: 100%;
111
+
112
+ @media (min-width: 768px) {
113
+ grid-template-columns: repeat(2, 1fr);
114
+ }
115
+
116
+ @media (min-width: 1024px) {
117
+ grid-template-columns: repeat(3, 1fr);
118
+ }
119
+
120
+ @media (min-width: 1536px) {
121
+ grid-template-columns: repeat(4, 1fr);
122
+ }
123
+ }
124
+
125
+ &__view-item {
126
+ display: flex;
127
+ align-items: center;
128
+ gap: 12px;
129
+ padding: 12px;
130
+ border: 1px solid var(--border-primary);
131
+ border-radius: 8px;
132
+ background-color: var(--surface-secondary);
133
+ min-width: 0;
134
+
135
+ &--hidden {
136
+ opacity: 0.5;
137
+ }
138
+ }
139
+
140
+ &__view-icon {
141
+ width: 24px;
142
+ height: 24px;
143
+ display: flex;
144
+ align-items: center;
145
+ justify-content: center;
146
+ color: var(--fill-primary);
147
+ flex-shrink: 0;
148
+
149
+ svg {
150
+ width: 24px;
151
+ height: 24px;
152
+ }
153
+ }
154
+
155
+ &__view-label {
156
+ @include typography('text.small.emphasis');
157
+ overflow: hidden;
158
+ text-overflow: ellipsis;
159
+ white-space: nowrap;
160
+ }
161
+
162
+ &__actions {
163
+ display: flex;
164
+ align-items: center;
165
+ gap: 24px;
166
+ margin-top: 8px;
167
+ }
168
+
169
+ &__save-btn {
170
+ @include typography('text.regular');
171
+ font-weight: 600;
172
+ padding: 10px 20px;
173
+ border-radius: 8px;
174
+ border: none;
175
+ background-color: var(--fill-action);
176
+ color: var(--label-white);
177
+ cursor: pointer;
178
+ transition: background-color 0.2s ease;
179
+
180
+ &:hover {
181
+ background-color: var(--actions-dark);
182
+ }
183
+
184
+ &:focus-visible {
185
+ outline: 2px solid var(--border-action);
186
+ outline-offset: 2px;
187
+ }
188
+ }
189
+
190
+ &__reset-btn {
191
+ @include typography('text.small');
192
+ font-weight: 500;
193
+ color: var(--label-secondary);
194
+ background: none;
195
+ border: none;
196
+ cursor: pointer;
197
+ padding: 0;
198
+
199
+ &:hover {
200
+ color: var(--label-primary);
201
+ text-decoration: underline;
202
+ }
203
+ }
204
+ }
@@ -0,0 +1,48 @@
1
+ import React, { useState } from 'react'
2
+ import type { Meta, StoryObj } from '@storybook/react'
3
+ import { SidebarCustomisation, defaultSidebarItems, SidebarItem } from './SidebarCustomisation'
4
+
5
+ const meta: Meta<typeof SidebarCustomisation> = {
6
+ title: 'V2/Pages/Settings/SidebarCustomisation',
7
+ component: SidebarCustomisation,
8
+ parameters: {
9
+ layout: 'padded',
10
+ },
11
+ }
12
+
13
+ export default meta
14
+ type Story = StoryObj<typeof SidebarCustomisation>
15
+
16
+ const InteractiveSidebarCustomisation = () => {
17
+ const [items, setItems] = useState<SidebarItem[]>(defaultSidebarItems)
18
+
19
+ const handleSave = (updatedItems: SidebarItem[]) => {
20
+ console.log('Saved items:', updatedItems)
21
+ alert('Settings saved!')
22
+ }
23
+
24
+ const handleReset = () => {
25
+ setItems(defaultSidebarItems)
26
+ console.log('Reset to defaults')
27
+ }
28
+
29
+ const handleCancel = () => {
30
+ console.log('Cancelled')
31
+ }
32
+
33
+ return (
34
+ <div style={{ maxWidth: '900px' }}>
35
+ <SidebarCustomisation
36
+ items={items}
37
+ onItemsChange={setItems}
38
+ onSave={handleSave}
39
+ onReset={handleReset}
40
+ onCancel={handleCancel}
41
+ />
42
+ </div>
43
+ )
44
+ }
45
+
46
+ export const Default: Story = {
47
+ render: () => <InteractiveSidebarCustomisation />,
48
+ }
@@ -0,0 +1,172 @@
1
+ import React, { useEffect, useState } from 'react'
2
+ import { SidebarNavItem } from './SidebarNavItem'
3
+ import './SidebarCustomisation.scss'
4
+ import {
5
+ CalendarIcon,
6
+ BookingsIcon,
7
+ BookingTypesIcon,
8
+ LoyaltyIcon,
9
+ CustomersIcon,
10
+ MarketingIcon,
11
+ WaiversIcon,
12
+ SettingsIcon,
13
+ EditIcon,
14
+ } from '../../../icons'
15
+
16
+ export interface SidebarItem {
17
+ id: string
18
+ label: string
19
+ icon: React.ReactNode
20
+ visible: boolean
21
+ locked?: boolean
22
+ }
23
+
24
+ export interface SidebarCustomisationProps {
25
+ items: SidebarItem[]
26
+ onItemsChange?: (items: SidebarItem[]) => void
27
+ onSave?: (items: SidebarItem[]) => void
28
+ onReset?: () => void
29
+ onCancel?: () => void
30
+ }
31
+
32
+ // Default sidebar items - IDs must match useProviderNavigation.tsx
33
+ export const defaultSidebarItems: SidebarItem[] = [
34
+ { id: 'events', label: 'Dates & Events', icon: <CalendarIcon />, visible: true },
35
+ { id: 'sales', label: 'Bookings & Enquiries', icon: <BookingsIcon />, visible: true },
36
+ { id: 'product-sets', label: 'Booking Types', icon: <BookingTypesIcon />, visible: true },
37
+ { id: 'loyalty', label: 'Loyalty', icon: <LoyaltyIcon />, visible: true },
38
+ { id: 'customers', label: 'Customers', icon: <CustomersIcon />, visible: true },
39
+ { id: 'emails', label: 'Email & SMS', icon: <MarketingIcon />, visible: true },
40
+ { id: 'waivers', label: 'Waivers', icon: <WaiversIcon />, visible: true },
41
+ { id: 'settings', label: 'Settings', icon: <SettingsIcon />, visible: true, locked: true },
42
+ ]
43
+
44
+ export const SidebarCustomisation: React.FC<SidebarCustomisationProps> = ({
45
+ items: initialItems,
46
+ onItemsChange,
47
+ onSave,
48
+ onReset,
49
+ onCancel,
50
+ }) => {
51
+ const [items, setItems] = useState<SidebarItem[]>(initialItems)
52
+ const [itemsBeforeEdit, setItemsBeforeEdit] = useState<SidebarItem[]>(initialItems)
53
+ const [isEditing, setIsEditing] = useState(false)
54
+
55
+ useEffect(() => {
56
+ setItems(initialItems)
57
+ if (!isEditing) {
58
+ setItemsBeforeEdit(initialItems)
59
+ }
60
+ }, [initialItems, isEditing])
61
+
62
+ const handleLabelChange = (id: string, newLabel: string) => {
63
+ const updatedItems = items.map((item) =>
64
+ item.id === id ? { ...item, label: newLabel } : item
65
+ )
66
+ setItems(updatedItems)
67
+ }
68
+
69
+ const handleSave = () => {
70
+ onItemsChange?.(items)
71
+ onSave?.(items)
72
+ setItemsBeforeEdit(items)
73
+ setIsEditing(false)
74
+ }
75
+
76
+ const handleReset = () => {
77
+ // Reset to defaults in UI - parent handles the actual default values
78
+ onReset?.()
79
+ }
80
+
81
+ const handleCancel = () => {
82
+ setItems(itemsBeforeEdit)
83
+ onCancel?.()
84
+ setIsEditing(false)
85
+ }
86
+
87
+ const handleEdit = () => {
88
+ setItemsBeforeEdit(items)
89
+ setIsEditing(true)
90
+ }
91
+
92
+ return (
93
+ <div className="sidebar-customisation">
94
+ <div className="sidebar-customisation__header">
95
+ <h3 className="sidebar-customisation__title">Sidebar Customisation</h3>
96
+ {isEditing ? (
97
+ <button
98
+ type="button"
99
+ className="sidebar-customisation__cancel-btn"
100
+ onClick={handleCancel}
101
+ >
102
+ Cancel
103
+ </button>
104
+ ) : (
105
+ <button
106
+ type="button"
107
+ className="sidebar-customisation__edit-btn"
108
+ onClick={handleEdit}
109
+ >
110
+ <EditIcon />
111
+ <span>Edit Side Bar</span>
112
+ </button>
113
+ )}
114
+ </div>
115
+
116
+ {isEditing ? (
117
+ <>
118
+ <div className="sidebar-customisation__grid">
119
+ {items.map((item) => {
120
+ const defaultItem = defaultSidebarItems.find(d => d.id === item.id)
121
+ return (
122
+ <SidebarNavItem
123
+ key={item.id}
124
+ id={item.id}
125
+ label={item.label}
126
+ defaultLabel={defaultItem?.label || item.label}
127
+ icon={item.icon}
128
+ onLabelChange={handleLabelChange}
129
+ />
130
+ )
131
+ })}
132
+ </div>
133
+
134
+ <div className="sidebar-customisation__actions">
135
+ <button
136
+ type="button"
137
+ className="sidebar-customisation__save-btn"
138
+ onClick={handleSave}
139
+ >
140
+ Save Changes
141
+ </button>
142
+ <button
143
+ type="button"
144
+ className="sidebar-customisation__reset-btn"
145
+ onClick={handleReset}
146
+ >
147
+ Reset to defaults
148
+ </button>
149
+ </div>
150
+ </>
151
+ ) : (
152
+ <div className="sidebar-customisation__view-grid">
153
+ {items.map((item) => (
154
+ <div
155
+ key={item.id}
156
+ className={`sidebar-customisation__view-item ${!item.visible ? 'sidebar-customisation__view-item--hidden' : ''}`}
157
+ >
158
+ <span className="sidebar-customisation__view-icon">
159
+ {item.icon}
160
+ </span>
161
+ <span className="sidebar-customisation__view-label">
162
+ {item.label}
163
+ </span>
164
+ </div>
165
+ ))}
166
+ </div>
167
+ )}
168
+ </div>
169
+ )
170
+ }
171
+
172
+ export default SidebarCustomisation
@@ -0,0 +1,76 @@
1
+ @import '../../../styles/tokens/typography';
2
+ @import '../../../styles/tokens/colors';
3
+
4
+ .sidebar-nav-item {
5
+ display: flex;
6
+ flex-direction: column;
7
+ gap: 8px;
8
+ font-family: var(--font-family-sans);
9
+
10
+ &__header {
11
+ display: flex;
12
+ align-items: center;
13
+ justify-content: space-between;
14
+ }
15
+
16
+ &__info {
17
+ display: flex;
18
+ align-items: center;
19
+ gap: 8px;
20
+
21
+ &--disabled {
22
+ .sidebar-nav-item__icon {
23
+ color: var(--fill-disabled);
24
+ }
25
+
26
+ .sidebar-nav-item__name {
27
+ color: var(--label-status-disabled);
28
+ }
29
+ }
30
+ }
31
+
32
+ &__icon {
33
+ width: 24px;
34
+ height: 24px;
35
+ display: flex;
36
+ align-items: center;
37
+ justify-content: center;
38
+ color: var(--fill-primary);
39
+
40
+ svg {
41
+ width: 24px;
42
+ height: 24px;
43
+ }
44
+ }
45
+
46
+ &__name {
47
+ @include typography('text.small.emphasis');
48
+ }
49
+
50
+ &__input {
51
+ @include typography('text.small');
52
+ height: 40px;
53
+ width: 100%;
54
+ padding: 8px 12px;
55
+ border: 1px solid var(--border-primary);
56
+ border-radius: 6px;
57
+ background-color: var(--surface-secondary);
58
+ color: var(--label-primary);
59
+ outline: none;
60
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
61
+
62
+ &::placeholder {
63
+ color: var(--label-secondary);
64
+ }
65
+
66
+ &:focus {
67
+ outline: none;
68
+ box-shadow: 0 0 0 2px var(--surface-primary), 0 0 0 4px var(--actions-regular);
69
+ }
70
+
71
+ &--disabled {
72
+ opacity: 0.5;
73
+ cursor: not-allowed;
74
+ }
75
+ }
76
+ }